我尝试使用snprintf将一些数字转换为字符串。 name1在逗号后应与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;
}
用以下内容编译:
gcc t.c -Wall
输出是:
./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
当iterMax较小时,结果是相同的(数字aftter逗号),例如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
ULLONG_MAX = 18446744073709551615比iterMax大。
我该如何解决?
TIA
答案 0 :(得分:5)
这实际上是double
精度的问题。还有很多其他问题可以解释更多有关IEEE-754浮点数的问题,但我在此总结了相关要点:
double
和家人有效地以科学记数法存储数字,精度有限。这意味着数字越大,它就越不准确。0.1
无法准确存储(相反,它类似于0.10000000149011612
)因此,数字100000000000.000010
是&#34;大&#34;,因此在小数位后变得不太准确。事实上,一旦你走向约4503599627370496
,你甚至不能存储所有整数!
答案 1 :(得分:1)
投射到long double
以获得更高的精确度:
snprintf(name1,length+1,"%Lf", (long double)iterMax+k*step);
输出:
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
答案 2 :(得分:0)
当打印超过DBL_DIG
个有效小数位数时,可能会出现double
有限格式的效果。
示例:
#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
有15位有效小数位数。 ('。'右边14')
无论用于double
的基数(2,10,16等),只有这么多的十进制数字
是“往返”的。
示例:(假设DBL_DIG为10,C指定的最小)
double x;
scanf("%lf", &x);
printf("%.*e\n", DBL_DIG - 1, x);
printf("%.*e\n", DBL_DIG - 1 + 5, x);
如果用户输入“12345678901234567890”,输出将为“1.234567890e19”和“1.234567890 ????? e19”,“?????”不是由C指定的。