473,387 Members | 1,575 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

printf on doubles

Code fragment:

#include <stdio.h>

int main (void)
{
double a = 1.0;
double b = 0.9999999999999999;

printf("%#12.5g\n", a);
printf("%#12.5g\n", b);

return 0;
}

I would expect the above to produce

1.0000
1.0000

but here it produces

1.0000
1.00000

Is this in conformity with the C standard? "Here" is linux, glibc
2.4, but I've seen the same thing on win32.

Allin Cottrell
Apr 5 '07 #1
6 2300
On Apr 4, 8:09 pm, Allin Cottrell <cottr...@wfu.eduwrote:
Code fragment:

#include <stdio.h>

int main (void)
{
double a = 1.0;
double b = 0.9999999999999999;

printf("%#12.5g\n", a);
printf("%#12.5g\n", b);

return 0;

}

I would expect the above to produce

1.0000
1.0000

but here it produces

1.0000
1.00000

Is this in conformity with the C standard? "Here" is linux, glibc
2.4, but I've seen the same thing on win32.
Here is what the standard says about the g format specifier:
"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), with the precision specifying the number of
significant digits. If the precision is zero, it is taken as 1. The
style used depends on the value converted; style e (or E) is used only
if the exponent resulting from such a conversion is less than −4 or
greater than or equal to the precision. Trailing zeros are removed
from the fractional portion of the result unless the # flag is
specified; a decimal-point character appears only if it is followed by
a digit. A double argument representing an infinity or NaN is
converted in the style of an f or F conversion specifier."

And here is the definition for the width and precision"
"* An optional minimum field width. If the converted value has fewer
characters than the field width, it is padded with spaces (by default)
on the left (or right, if the left adjustment flag, described later,
has been given) to the field width. The field width takes the form of
an asterisk * (described later) or a decimal integer.232)
* An optional precision that gives the minimum number of digits to
appear for the d, i, o, u, x, and X conversions, the number of digits
to appear after the decimal-point character for a, A, e, E, f, and F
conversions, the maximum number of significant digits for the g and G
conversions, or the maximum number of bytes to be written for s
conversions. The precision takes the form of a period (.) followed
either by an asterisk * (described later) or by an optional decimal
integer; if only the period is specified, the precision is taken as
zero. If a precision appears with any other conversion specifier, the
behavior is undefined."

I am not sure how the C compiler computes significant digits, but it
seems logical to me that both outputs should look the same. Probably,
news:comp.std.c can offer the best explanation.

Apr 5 '07 #2
user923005 wrote:
On Apr 4, 8:09 pm, Allin Cottrell <cottr...@wfu.eduwrote:
>Code fragment:

#include <stdio.h>

int main (void)
{
double a = 1.0;
double b = 0.9999999999999999;

printf("%#12.5g\n", a);
printf("%#12.5g\n", b);

return 0;

}

I would expect the above to produce

1.0000
1.0000

but here it produces

1.0000
1.00000

Is this in conformity with the C standard? "Here" is linux, glibc
2.4, but I've seen the same thing on win32.

Here is what the standard says about the g format specifier:
"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), with the precision specifying the number of
significant digits... Trailing zeros are removed
from the fractional portion of the result unless the # flag is
specified; a decimal-point character appears only if it is followed by
a digit...

And here is the definition for the ... precision"
* An optional precision that gives the minimum number of digits to
appear for the d, i, o, u, x, and X conversions, the number of digits
to appear after the decimal-point character for a, A, e, E, f, and F
conversions, the maximum number of significant digits for the g and G
conversions...
Thanks. Now I'm not sure whether this is a bug in the C library
implementation, or a bug in the C standard.

Since I used the g format specifier I expect style f or e output,
and I expect that the given precision (namely, 5) should specify the
number of significant digits (from the first paragraph above).

However, the "loophole" (contradiction?) is that in the second
paragraph, the precision for an 'e' conversion is not the number of
significant digits, but the number of digits appearing after the
decimal point.

It would seem that a = 1.0 has been printed in style e with 5
significant digits, while b = 0.999... has been printed in
style f with 5 digits after the point. Is this supposed to be
permissible, based on the input?

Allin Cottrell

Apr 5 '07 #3
Allin Cottrell wrote:
It would seem that a = 1.0 has been printed in style e with 5
significant digits, while b = 0.999... has been printed in
style f with 5 digits after the point. Is this supposed to be
permissible, based on the input?
Sorry, this is confused. a = 1.0 is obviously not printed in
style e in the output I showed Both 1.0 and 0.999... are printed
in style f. But according to the standard the usual business
whereby the precision gives the number of digits after the decimal
point in style f, ought to be over-ridden by the fact that this
is a "pass-through" from the g format, in favor of the precision's
giving the number of significant digits. In which case the
representation of 0.999... as "1.00000" is plain wrong, no?

Allin Cottrell


Apr 6 '07 #4
user923005 wrote:
On Apr 4, 8:09 pm, Allin Cottrell <cottr...@wfu.eduwrote:
printf("%#12.5g\n", a);
printf("%#12.5g\n", b);
but here it produces
1.0000
1.00000
Is this in conformity with the C standard? ...
I am not sure how the C compiler computes significant digits, but it
seems logical to me that both outputs should look the same.
The simple answer is, no, that is not conforming.
Apr 6 '07 #5
On Apr 4, 8:09 pm, Allin Cottrell <cottr...@wfu.eduwrote:
Code fragment:

#include <stdio.h>

int main (void)
{
double a = 1.0;
double b = 0.9999999999999999;

printf("%#12.5g\n", a);
printf("%#12.5g\n", b);

return 0;

}

I would expect the above to produce

1.0000
1.0000

but here it produces

1.0000
1.00000

Is this in conformity with the C standard? "Here" is linux, glibc
2.4, but I've seen the same thing on win32.

Allin Cottrell
I get correct output on GCC with MINGW on Win32:

dcorbit@DCORBIT64 /c/tmp
$ gcc -W -Wall -ansi -pedantic broke.c

dcorbit@DCORBIT64 /c/tmp
$ ./a
1.0000
1.0000

dcorbit@DCORBIT64 /c/tmp
$ gcc --version
gcc.exe (GCC) 4.0.1 20050608 (prerelease)
Copyright (C) 2005 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There
is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.

Also with MS VC++:
C:\tmp>vsvars32
Setting environment for using Microsoft Visual Studio 2005 x86 tools.

C:\tmp>cl /W4 /Ox broke.c
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42
for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

broke.c
Microsoft (R) Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation. All rights reserved.

/out:broke.exe
broke.obj

C:\tmp>broke
1.0000
1.0000

You should send a bug report to the glibc folks.

Apr 6 '07 #6
user923005 wrote:
On Apr 4, 8:09 pm, Allin Cottrell <cottr...@wfu.eduwrote:
>Code fragment:

#include <stdio.h>

int main (void)
{
double a = 1.0;
double b = 0.9999999999999999;

printf("%#12.5g\n", a);
printf("%#12.5g\n", b);

return 0;

}

I would expect the above to produce

1.0000
1.0000

but here it produces

1.0000
1.00000
You should send a bug report to the glibc folks.
Thanks, will do!

Allin Cottrell
Apr 6 '07 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

13
by: Yogesh Khanolkar | last post by:
Hi, I am getting incorrect o/p from the code below: #include<stdio.h> #include<float.h> #include<limits.h> main() { double val,val1;
5
by: dustu | last post by:
Hi, I'm using lcc-win32 on Windows 2000 as compiler/IDE. The details are: Input file (sample - the no. of digits per line may change): ---> 1111111111111111.00 1111111111111111.01...
9
by: | last post by:
void show( char *s, ...) is a function seemd like prinf code -------------- #include <stdio.h> #include <stdarg.h> void show( char *s, ...) { va_list stage;
2
by: David Mathog | last post by:
Is there some method for restricting the maximum number of characters that will be emitted by a printf() function? Where printf() here is generic and refers to sprintf, fprintf, etc. Here's an...
69
by: fieldfallow | last post by:
Hello all, Before stating my question, I should mention that I'm fairly new to C. Now, I attempted a small demo that prints out the values of C's numeric types, both uninitialised and after...
12
by: Zero | last post by:
Hi everybody, i want to write a small program, which shows me the biggest and smallest number in dependance of the data type. For int the command could be: ...
34
by: Old Wolf | last post by:
Is there any possible situation for printf where %hd causes a different result to %d, and the corresponding argument was of type 'short int' ?
11
by: vectorizor | last post by:
Hi guys, My program deals with with lots of large matrices. To easily debug it, I would like to be able to dump them in files, so that I can easily import then in other software (think matlab,...
2
by: wombat | last post by:
Is there a way to prevent rounding when using printf for print a double/float? Example: double x=3.51; printf("%.0f\n", x); The output of this is 4, when I want it to be 3.
29
by: candy_init | last post by:
Hi all, I just came across the following program: #include <stdio.h> int main() { float a = 12.5; printf("%d\n", a); printf("%d\n", *(int *)&a); return 0;
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.