更新时间:2022-10-16 11:58:13
$ c> double 精度。还有很多其他问题可以解释更多关于IEEE-754浮点数的问题,但我将在这里总结相关的几点:
double
和family以有限的精度有效地以科学记数法存储数字。这意味着数字越大,准确度越低。 0.1
不能准确存储(相反,它的内容类似于 0.10000000149011612
)例如 100000000000.000010
的数字是大,所以在小数点后面变得不准确。事实上,一旦你接近 4503599627370496
,你甚至不能存储所有的整数!
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
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!