Reputation: 1386
I try to convert some numbers to string using snprintf. The name1 should have the same digits after comma as name2.
#include <stdio.h>
#define length 50
int main()
{
char name1 [length];
char name2 [length];
double step= 0.00001;
unsigned long long int iterMax =100000000000;
int k;
for (k = 0; k <= 20; k++)
{ printf("numbers : k = %2d ; k*step = %f ;", k, k*step);
snprintf(name1,length+1,"%f", iterMax+k*step); /* */
snprintf(name2,length+1, " %f", k*step); /* */
printf("strings : k*step = %s ; iterMax+k*step = %s \n",name2, name1);
}
return 0;
}
Compile it with :
gcc t.c -Wall
Output is :
./a.out
numbers : k = 0 ; k*step = 0.000000 ;strings : k*step = 0.000000 ; iterMax+k*step = 100000000000.000000
numbers : k = 1 ; k*step = 0.000010 ;strings : k*step = 0.000010 ; iterMax+k*step = 100000000000.000015
numbers : k = 2 ; k*step = 0.000020 ;strings : k*step = 0.000020 ; iterMax+k*step = 100000000000.000015
numbers : k = 3 ; k*step = 0.000030 ;strings : k*step = 0.000030 ; iterMax+k*step = 100000000000.000031
numbers : k = 4 ; k*step = 0.000040 ;strings : k*step = 0.000040 ; iterMax+k*step = 100000000000.000046
The results are the same ( digits aftter comma ) when iterMax is smaller , for example 100000000 :
numbers : k = 0 ; k*step = 0.000000 ;strings : k*step = 0.000000 ; iterMax+k*step = 100000000.000000
numbers : k = 1 ; k*step = 0.000010 ;strings : k*step = 0.000010 ; iterMax+k*step = 100000000.000010
numbers : k = 2 ; k*step = 0.000020 ;strings : k*step = 0.000020 ; iterMax+k*step = 100000000.000020
numbers : k = 3 ; k*step = 0.000030 ;strings : k*step = 0.000030 ; iterMax+k*step = 100000000.000030
numbers : k = 4 ; k*step = 0.000040 ;strings : k*step = 0.000040 ; iterMax+k*step = 100000000.000040
The ULLONG_MAX = 18446744073709551615 is greater then iterMax.
How can I resolve that ?
TIA
Upvotes: 0
Views: 162
Reputation: 153498
When printing more than DBL_DIG
significant decimal digits, the effects of a double
finite format may appear.
Example:
#include <float.h>
printf("%d\n", DBL_DIG);
printf("%.*e\n", DBL_DIG - 1, 100000000000.0 + 0.00001);
printf("%.*e\n", DBL_DIG - 1 + 10, 100000000000.0 + 0.00001);
15
1.00000000000000e+11
1.000000000000000152587891e+11
1.00000000000000e+11
has 15 significant decimal digits. (14 to the right of '.')
Regardless of the base (2, 10, 16, etc.) used for a double
, only so many decimal digits
are "round-trip"-able.
Example: (Assuming DBL_DIG is 10, the minimum specified by C)
double x;
scanf("%lf", &x);
printf("%.*e\n", DBL_DIG - 1, x);
printf("%.*e\n", DBL_DIG - 1 + 5, x);
Should the user entered "12345678901234567890", the output would be "1.234567890e19" and "1.234567890?????e19", the "?????" not begin specified by C.
Upvotes: 0
Reputation: 11706
This is actually a problem of double
precision. There are plenty of other questions which explain more about IEEE-754 floating-point numbers, but I'll sum up the relevant points here:
double
and family effectively store numbers in scientific notation with limited precision. This means the larger the number, the less accurate it'll be.0.1
cannot be stored exactly (instead, it's something like 0.10000000149011612
)As such, the number 100000000000.000010
is "large", so it becomes less accurate after the decimal place. In fact, once you get towards about 4503599627370496
, you can't even store all integers!
Upvotes: 5
Reputation: 41017
Cast to a long double
in order to get more precision:
snprintf(name1,length+1,"%Lf", (long double)iterMax+k*step);
Output:
numbers : k = 0 ; k*step = 0.000000 ;strings : k*step = 0.000000 ; iterMax+k*step = 100000000000.000000
numbers : k = 1 ; k*step = 0.000010 ;strings : k*step = 0.000010 ; iterMax+k*step = 100000000000.000010
numbers : k = 2 ; k*step = 0.000020 ;strings : k*step = 0.000020 ; iterMax+k*step = 100000000000.000020
numbers : k = 3 ; k*step = 0.000030 ;strings : k*step = 0.000030 ; iterMax+k*step = 100000000000.000030
numbers : k = 4 ; k*step = 0.000040 ;strings : k*step = 0.000040 ; iterMax+k*step = 100000000000.000040
numbers : k = 5 ; k*step = 0.000050 ;strings : k*step = 0.000050 ; iterMax+k*step = 100000000000.000050
numbers : k = 6 ; k*step = 0.000060 ;strings : k*step = 0.000060 ; iterMax+k*step = 100000000000.000060
numbers : k = 7 ; k*step = 0.000070 ;strings : k*step = 0.000070 ; iterMax+k*step = 100000000000.000070
numbers : k = 8 ; k*step = 0.000080 ;strings : k*step = 0.000080 ; iterMax+k*step = 100000000000.000080
numbers : k = 9 ; k*step = 0.000090 ;strings : k*step = 0.000090 ; iterMax+k*step = 100000000000.000090
numbers : k = 10 ; k*step = 0.000100 ;strings : k*step = 0.000100 ; iterMax+k*step = 100000000000.000100
numbers : k = 11 ; k*step = 0.000110 ;strings : k*step = 0.000110 ; iterMax+k*step = 100000000000.000110
numbers : k = 12 ; k*step = 0.000120 ;strings : k*step = 0.000120 ; iterMax+k*step = 100000000000.000120
numbers : k = 13 ; k*step = 0.000130 ;strings : k*step = 0.000130 ; iterMax+k*step = 100000000000.000130
numbers : k = 14 ; k*step = 0.000140 ;strings : k*step = 0.000140 ; iterMax+k*step = 100000000000.000140
numbers : k = 15 ; k*step = 0.000150 ;strings : k*step = 0.000150 ; iterMax+k*step = 100000000000.000150
numbers : k = 16 ; k*step = 0.000160 ;strings : k*step = 0.000160 ; iterMax+k*step = 100000000000.000160
numbers : k = 17 ; k*step = 0.000170 ;strings : k*step = 0.000170 ; iterMax+k*step = 100000000000.000170
numbers : k = 18 ; k*step = 0.000180 ;strings : k*step = 0.000180 ; iterMax+k*step = 100000000000.000180
numbers : k = 19 ; k*step = 0.000190 ;strings : k*step = 0.000190 ; iterMax+k*step = 100000000000.000190
numbers : k = 20 ; k*step = 0.000200 ;strings : k*step = 0.000200 ; iterMax+k*step = 100000000000.000200
Upvotes: 1