为什么snprintf更改输出字符串? [英] Why snprintf changes output string?
问题描述
我尝试使用snprintf将一些数字转换为字符串。 name1应该与name2之后的逗号相同。
#include< stdio.h>
#define长度50
int main()
{
char name1 [length];
char name2 [length];
double step = 0.00001;
unsigned long long int iterMax = 100000000000;
int k; (k = 0; k <= 20; k ++)
{printf(numbers:k =%2d; k * step =%f;,k,k *步);
snprintf(name1,length + 1,%f,iterMax + k * step); / * * /
snprintf(name2,length + 1,%f,k * step); / * * /
printf(strings:k * step =%s; iterMax + k * step =%s \\\
,name2,name1);
}
返回0;
$ / code>
使用以下内容编译它:
gcc tc -Wall
输出为:
./ a.out
数字:k = 0; k * step = 0.000000;字符串:k * step = 0.000000; iterMax + k * step = 100000000000.000000
numbers:k = 1; k * step = 0.000010;字符串:k * step = 0.000010; iterMax + k * step = 100000000000.000015
数字:k = 2; k * step = 0.000020;字符串:k * step = 0.000020; iterMax + k * step = 100000000000.000015
数字:k = 3; k * step = 0.000030;字符串:k * step = 0.000030; iterMax + k * step = 100000000000.000031
numbers:k = 4; k * step = 0.000040;字符串:k * step = 0.000040; iterMax + k * step = 100000000000.000046
当iterMax较小时,结果相同(数字为逗号) ,例如100000000:
数字:k = 0; k * step = 0.000000;字符串:k * step = 0.000000; iterMax + k * step = 100000000.000000
numbers:k = 1; k * step = 0.000010;字符串:k * step = 0.000010; iterMax + k * step = 100000000.000010
numbers:k = 2; k * step = 0.000020;字符串:k * step = 0.000020; iterMax + k * step = 100000000.000020
numbers:k = 3; k * step = 0.000030;字符串:k * step = 0.000030; iterMax + k * step = 100000000.000030
numbers:k = 4; k * step = 0.000040;字符串:k * step = 0.000040; iterMax + k * step = 100000000.000040
ULLONG_MAX = 18446744073709551615大于iterMax。
我该如何解决这个问题?
TIA
$ c> double 精度。还有很多其他问题可以解释更多关于IEEE-754浮点数的问题,但我将在这里总结相关的几点:
-
double
和family以有限的精度有效地以科学记数法存储数字。这意味着数字越大,准确度越低。
- 大多数数字都使用基数2.因此,小数
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.- Most numbers use base 2. As such, the decimal
0.1
cannot be stored exactly (instead, it's something like0.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!
这篇关于为什么snprintf更改输出字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!