How %g works in printf - c

The %g description says
Use the shortest representation: %e or %f
for example,
544666.678 is written as 544667 if %.6g is used which is fine.
But the same number is written as 5.4467E+5 when %.5g is used.
Why would it use exponential notation (%e) here while 544670 (%f) is shorter in length than that.
Can anyone please help me to understand? Is this a bug?
Similarly, 44.35 is written as 44.4 when %.1f is used which is fine.
but 44.55 is written as 44.5 when %.1f is used. Why isn't it written as 44.6? Is this a bug?

Use the shortest representation: %e or %f is not precise enough.
C11 7.21.6.1 The fprintf function
A double argument representing a floating-point number is converted in style f or e (or in style F or E in the case of a G conversion specifier), depending on the value converted and the precision. Let P equal the precision if nonzero, 6 if the precision is omitted, or 1 if the precision is zero. Then, if a conversion with style E would have an exponent of X :
— if P > X ≥ −4, the conversion is with style f (or F) and precision P − (X + 1).
— otherwise, the conversion is with style e (or E) and precision P − 1.
Finally, unless the # flag is used, any trailing zeros are removed from the fractional portion of the result and the decimal-point character is removed if there is no fractional portion remaining.
So in the example of %.5g with 544666.678, P is 5, and X being 5, according to the rule, the style e is used because P > X ≥ −4 is false.

Related

How to use printf so that zeros are printed with decimals

I'm running a simple calculation in C, for which, sometimes, the result is exactly 0. I then print these results using something like printf("%0.4g", result). If the result is not 0, it does what I want it do, e.g., the output may be 1.796e+04. However, if the result is exactly 0, which it often is, the output will be 0.
My question is, what can I do to print 0.0000, with 4 decimals, even though the number there might be exactly 0?
To have 4 decimals, you have to specify .5. To have 0 print as 0.0, you have to add #.
printf("%#.5g", 0.0);
Note that this will print 4 decimal places, unlike %0.4g, that will print 3 decimal places.
The 0 before the dot . is unneeded. It is used to specify, that the field should be prefixed with zeros not with spaces when matching a field length. But you don't specify the field length, so no prefixing takes place, so the 0 can be left out.
Using the %g format with the # modifier probably does what you want.
The POSIX specification for printf() (which is generally a superset of C11 §7.21.6.1 The printf() function, but here POSIX says the same as C11) requires:
g, G — The double argument representing a floating-point number shall be converted in the style f or e (or in the style F or E in the case of a G conversion specifier), depending on the value converted and the precision. Let P equal the precision if non-zero, 6 if the precision is omitted, or 1 if the precision is zero. Then, if a conversion with style E would have an exponent of X:
If P > X >= -4, the conversion shall be with style f (or F) and precision P-(X+1).
Otherwise, the conversion shall be with style e (or E) and precision P -1.
Finally, unless the '#' flag is used, any trailing zeros shall be removed from the fractional portion of the result and the decimal-point character shall be removed if there is no fractional portion remaining.
A double argument representing an infinity or NaN shall be converted in the style of an f or F conversion specifier.
So, the trailing zeroes you want are retained by specifying # in the conversion specification — "%#0.4g".
If you want 4 digits after the decimal point though, you need to use "%#0.5g".
Sample code:
#include <stdio.h>
int main(void)
{
double data[] = { 0.0, -0.0000001, +1.234E-6, 1.796e+04, 3.14159265, 6.022140857E+23, 6.62607004E-34 };
enum { NUM_DATA = sizeof(data) / sizeof(data[0]) };
for (int i = 0; i < NUM_DATA; i++)
printf("%20.10g = %#0.4g\n", data[i], data[i]);
return 0;
}
Output (Mac running macOS 10.14.4 Mojave — home-built GCC 9.1.0 compiler):
0 = 0.000
-1e-07 = -1.000e-07
1.234e-06 = 1.234e-06
17960 = 1.796e+04
3.14159265 = 3.142
6.022140857e+23 = 6.022e+23
6.62607004e-34 = 6.626e-34
You do recognize approximations to Planck's Constant and Avogadro's Number, don't you?
the statement
printf("%0.4e\n", res);
might solve your problem!
You can use
printf("%0.4f",YourVeriable);

What precisely does the %g printf specifier mean?

The %g specifier doesn't seem to behave in the way that most sources document it as behaving.
According to most sources I've found, across multiple languages that use printf specifiers, the %g specifier is supposed to be equivalent to either %f or %e - whichever would produce shorter output for the provided value. For instance, at the time of writing this question, cplusplus.com says that the g specifier means:
Use the shortest representation: %e or %f
And the PHP manual says it means:
g - shorter of %e and %f.
And here's a Stack Overflow answer that claims that
%g uses the shortest representation.
And a Quora answer that claims that:
%g prints the number in the shortest of these two representations
But this behaviour isn't what I see in reality. If I compile and run this program (as C or C++ - it's a valid program with the same behaviour in both):
#include <stdio.h>
int main(void) {
double x = 123456.0;
printf("%e\n", x);
printf("%f\n", x);
printf("%g\n", x);
printf("\n");
double y = 1234567.0;
printf("%e\n", y);
printf("%f\n", y);
printf("%g\n", y);
return 0;
}
... then I see this output:
1.234560e+05
123456.000000
123456
1.234567e+06
1234567.000000
1.23457e+06
Clearly, the %g output doesn't quite match either the %e or %f output for either x or y above. What's more, it doesn't look like %g is minimising the output length either; y could've been formatted more succinctly if, like x, it had not been printed in scientific notation.
Are all of the sources I've quoted above lying to me?
I see identical or similar behaviour in other languages that support these format specifiers, perhaps because under the hood they call out to the printf family of C functions. For instance, I see this output in Python:
>>> print('%g' % 123456.0)
123456
>>> print('%g' % 1234567.0)
1.23457e+06
In PHP:
php > printf('%g', 123456.0);
123456
php > printf('%g', 1234567.0);
1.23457e+6
In Ruby:
irb(main):024:0* printf("%g\n", 123456.0)
123456
=> nil
irb(main):025:0> printf("%g\n", 1234567.0)
1.23457e+06
=> nil
What's the logic that governs this output?
This is the full description of the g/G specifier in the C11 standard:
A double argument representing a floating-point number is
converted in style f or e (or in style F or E in the case of a G
conversion specifier), depending on the value converted and the
precision. Let P equal the precision if nonzero, 6 if the precision is
omitted, or 1 if the precision is zero. Then, if a conversion with
style E would have an exponent of X:
if P > X ≥ −4, the conversion is
with style f (or F) and precision P − (X + 1).
otherwise, the
conversion is with style e (or E) and precision P − 1.
Finally, unless
the # flag is used, any trailing zeros are removed from the fractional
portion of the result and the decimal-point character is removed if
there is no fractional portion remaining.
A double argument
representing an infinity or NaN is converted in the style of an f or F
conversion specifier.
This behaviour is somewhat similar to simply using the shortest representation out of %f and %e, but not equivalent. There are two important differences:
Trailing zeros (and, potentially, the decimal point) get stripped when using %g, which can cause the output of a %g specifier to not exactly match what either %f or %e would've produced.
The decision about whether to use %f-style or %e-style formatting is made based purely upon the size of the exponent that would be needed in %e-style notation, and does not directly depend on which representation would be shorter. There are several scenarios in which this rule results in %g selecting the longer representation, like the one shown in the question where %g uses scientific notation even though this makes the output 4 characters longer than it needs to be.
In case the C standard's wording is hard to parse, the Python documentation provides another description of the same behaviour:
General format. For a given precision p >= 1,
this rounds the number to p significant digits and
then formats the result in either fixed-point format
or in scientific notation, depending on its magnitude.
The precise rules are as follows: suppose that the
result formatted with presentation type 'e' and
precision p-1 would have exponent exp. Then
if -4 <= exp < p, the number is formatted
with presentation type 'f' and precision
p-1-exp. Otherwise, the number is formatted
with presentation type 'e' and precision p-1.
In both cases insignificant trailing zeros are removed
from the significand, and the decimal point is also
removed if there are no remaining digits following it.
Positive and negative infinity, positive and negative
zero, and nans, are formatted as inf, -inf,
0, -0 and nan respectively, regardless of
the precision.
A precision of 0 is treated as equivalent to a
precision of 1. The default precision is 6.
The many sources on the internet that claim that %g just picks the shortest out of %e and %f are simply wrong.
My favorite format for doubles is "%.15g". It seems to do the right thing in every case. I'm pretty sure 15 is the maximum reliable decimal precision in a double as well.

From when format specifier '%g' for double starts printing in exponential format

I would like to understand from when format specifier %g for double starts printing values in exponential format.
myTest.c
#include <stdio.h>
int main() {
double val = 384615.38462;
double val2 = 9999999;
printf ("val = %g\n",val);
printf ("val2 = %g\n",val2);
return 0;
}
Compiled using gcc :
gcc version 4.5.2 (GCC)
Target: i386-pc-solaris2.11
Output :
val = 384615
val2 = 1e+07
Question:
Why val is printed as integer and why val2 has been converted to exponential format even when I have not used %lf in printf.
Is there a range from when it will start print values using exponential format? If yes, Is there any way we can guess what could be the value range ?
Thanks in Advance.
According to the man 3 printf:
g, G
The double argument is converted in style f or e (or F or E for G conversions). The precision specifies the number of significant digits. If the precision is missing, 6 digits are given; if the precision is zero, it is treated as 1. Style e is used if the exponent from its conversion is less than -4 or greater than or equal to the precision. Trailing zeros are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit.
And the C11 – ISO/IEC 9899:2011 standard draft N1570 (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf):
g,G
A double argument representing a floating-point number is converted in
style f or e (or in style F or E in the case of a G conversion specifier),
depending on the value converted and the precision. Let P equal the
precision if nonzero, 6 if the precision is omitted, or 1 if the precision is zero.
Then, if a conversion with style E would have an exponent of X:
— if P > X ≥ −4, the conversion is with style f (or F) and precision
P − (X + 1).
— otherwise, the conversion is with style e (or E) and precision P − 1.
Finally, unless the # flag is used, any trailing zeros are removed from the
fractional portion of the result and the decimal-point character is removed if
there is no fractional portion remaining.
A double argument representing an infinity or NaN is converted in the style
of an f or F conversion specifier.
The man says
g, G
The double argument is converted in style f or e (or F or E for G conversions). The precision specifies the number of significant digits. If the precision is missing, 6 digits are given; if the precision is zero, it is treated as 1. Style e is used if the exponent from its conversion is less than -4 or greater than or equal to the precision. Trailing zeros are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit.

What does the numerical literal 0.e0f mean?

I am currently trying to debug an uninitialized memory error. I have now come across the numerical literal 0.e0f in the OpenBlas source code (which is what the debugger is currently at) what does that mean?
The context is this:
if ((alpha_r == 0.e0f) && (alpha_i == 0.e0f)) return;
The 0.e0f evaluates to 0 apparently.
A floating-point literals have two syntaxes. The first one consists of the following parts:
nonempty sequence of decimal digits containing a decimal point character (defines significand)
(optional) e or E followed with optional minus or plus sign and nonempty sequence of decimal digits (defines exponent)
(optional) a suffix type specifier as a l, f, L or F
The second one consists of the following parts:
nonempty sequence of decimal digits (defines significant)
e or E followed with optional minus or plus sign and nonempty sequence of decimal digits (defines exponent)
(optional) a suffix type specifier as a l, f, L or F
The suffix type specifier defines the actual type of the floating-point literal:
(no suffix) defines double
f F defines float
l L defines long double
f floating point indicator
eX is exponent value for 10 to the power of X. for example e5 means 10 to the 5 which is 100000. or e-3 means 0.001.
Combining the two
1.23e-3f --> 1.23 x 10 ^ -3 = 0.00123
By expanding your example it is
0.e0f --> 0.0 x 10 ^ 0 = 0.0 (in floating point format)
PS: A useful programming practice. Never ever (see PS2) compare two floating point numbers for equality.
There are some values cannot be represented exactly by floating points just approximations.
Like this example
0.3 + 0.6 = 0.89999999999999991 != 0.9
Instead use:
float a;
float b;
....
if( abs(a-b) < FLT_EPSILON )
FLT_EPLISON is a very small floating point value where 1.0 + FLT_EPSILON != 1.0. (example 0.1e-10) (Quoted from #AlterMann)
abs is short for absolute function for floating points; which in std is fabs. Can be found in other libraries with different names too.
PS 2: OK... Never ever had been a little strong. I didn't mean that this piece of code is wrong neither as algorithm nor syntax. Question itself is a bit simple though this warning may help the new programmers end up here.
As in comments stated this code example is appropriate for checking. 0 check is a valid operation, because current standards for floating point representation guarantee that 0 can be expressed.
It's zero in scientific notation, as single-precision floating point, with a redundant decimal mark. It's the same thing as 0e0.
That's a 0 of type float.
See 6.4.4.2 in the C99 Standard ( http://port70.net/~nsz/c/c99/n1256.html#6.4.4.2 )
In my opinion a plain 0 would be better irrespective of the type of alpha_r and alpha_i
if ((alpha_r == 0) && (alpha_i == 0)) return;

What is the difference between %g and %f in C?

I was going through The C programming Language by K&R. Here in a statement to print a double variable it is written
printf("\t%g\n", sum += atof(line));
where sum is declared as double. Can anybody please help me out when to use %g in case of double or in case of float and whats the difference between %g and %f.
They are both examples of floating point input/output.
%g and %G are simplifiers of the scientific notation floats %e and %E.
%g will take a number that could be represented as %f (a simple float or double) or %e (scientific notation) and return it as the shorter of the two.
The output of your print statement will depend on the value of sum.
See any reference manual, such as the man page:
f,F
The double argument is rounded and converted to decimal notation in the style [-]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is explicitly zero, no decimal-point character appears. If a decimal point appears, at least one digit appears before it.
(The SUSv2 does not know about F and says that character string representations for infinity and NaN may be made available. The C99 standard specifies '[-]inf' or '[-]infinity' for infinity, and a string starting with 'nan' for NaN, in the case of f conversion, and '[-]INF' or '[-]INFINITY' or 'NAN*' in the case of F conversion.)
g,G
The double argument is converted in style f or e (or F or E for G conversions). The precision specifies the number of significant digits. If the precision is missing, 6 digits are given; if the precision is zero, it is treated as 1. Style e is used if the exponent from its conversion is less than -4 or greater than or equal to the precision. Trailing zeros are removed from the fractional part of the result; a decimal point appears only if it is followed by at least one digit.
E = exponent expression, simply means power(10, n) or 10 ^ n
F = fraction expression, default 6 digits precision
G = gerneral expression, somehow smart to show the number in a concise way (but
really?)
See the below example,
The code
void main(int argc, char* argv[])
{
double a = 4.5;
printf("=>>>> below is the example for printf 4.5\n");
printf("%%e %e\n",a);
printf("%%f %f\n",a);
printf("%%g %g\n",a);
printf("%%E %E\n",a);
printf("%%F %F\n",a);
printf("%%G %G\n",a);
double b = 1.79e308;
printf("=>>>> below is the exbmple for printf 1.79*10^308\n");
printf("%%e %e\n",b);
printf("%%f %f\n",b);
printf("%%g %g\n",b);
printf("%%E %E\n",b);
printf("%%F %F\n",b);
printf("%%G %G\n",b);
double d = 2.25074e-308;
printf("=>>>> below is the example for printf 2.25074*10^-308\n");
printf("%%e %e\n",d);
printf("%%f %f\n",d);
printf("%%g %g\n",d);
printf("%%E %E\n",d);
printf("%%F %F\n",d);
printf("%%G %G\n",d);
}
The output
=>>>> below is the example for printf 4.5
%e 4.500000e+00
%f 4.500000
%g 4.5
%E 4.500000E+00
%F 4.500000
%G 4.5
=>>>> below is the exbmple for printf 1.79*10^308
%e 1.790000e+308
%f 178999999999999996376899522972626047077637637819240219954027593177370961667659291027329061638406108931437333529420935752785895444161234074984843178962619172326295244262722141766382622299223626438470088150218987997954747866198184686628013966119769261150988554952970462018533787926725176560021258785656871583744.000000
%g 1.79e+308
%E 1.790000E+308
%F 178999999999999996376899522972626047077637637819240219954027593177370961667659291027329061638406108931437333529420935752785895444161234074984843178962619172326295244262722141766382622299223626438470088150218987997954747866198184686628013966119769261150988554952970462018533787926725176560021258785656871583744.000000
%G 1.79E+308
=>>>> below is the example for printf 2.25074*10^-308
%e 2.250740e-308
%f 0.000000
%g 2.25074e-308
%E 2.250740E-308
%F 0.000000
%G 2.25074E-308
As Unwind points out f and g provide different default outputs.
Roughly speaking if you care more about the details of what comes after the decimal point I would do with f and if you want to scale for large numbers go with g. From some dusty memories f is very nice with small values if your printing tables of numbers as everything stays lined up but something like g is needed if you stand a change of your numbers getting large and your layout matters. e is more useful when your numbers tend to be very small or very large but never near ten.
An alternative is to specify the output format so that you get the same number of characters representing your number every time.
Sorry for the woolly answer but it is a subjective out put thing that only gets hard answers if the number of characters generated is important or the precision of the represented value.
%g removes trailing zeros in floats,
prints (integer) upto 10**6 , after that in e+ upto precision 6
123456 gives 123456
1234567 gives 1.23457e+06
prints (float > 10** -4 ) upto precision 6 , after that rounds off to pre. 6
1.23456 gives 1.23456
1.234567 gives 1.23457
print (float < 10** -4 ) upto precision 4 , else in ne-0p
0.0001 gives 0.0001
0.000001 gives 1e-06
0.12345678 gives 0.123457
%G does the same , but exp(e) becomes exp(E)
%f and %g does the same thing. Only difference is that %g is the shorter form of %f. That is the precision after decimal point is larger in %f compared to %g

Resources