为什么snprintf更改输出字符串?

Ada*_*dam 0 c printf gcc

我尝试使用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;
}
Run Code Online (Sandbox Code Playgroud)

编译它:

 gcc t.c  -Wall
Run Code Online (Sandbox Code Playgroud)

输出是:

./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 
Run Code Online (Sandbox Code Playgroud)

当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 
Run Code Online (Sandbox Code Playgroud)

ULLONG_MAX = 18446744073709551615比iterMax大.

我怎么解决这个问题?

TIA

Dre*_*wen 5

这实际上是一个double精确的问题.还有很多其他问题可以解释更多有关IEEE-754浮点数的问题,但我将在此总结相关要点:

  1. double和家庭有效地以科学记数法存储数字,精度有限.这意味着数字越大,它的准确度就越低.
  2. 大多数数字使用基数2.因此,小数0.1不能精确存储(相反,它是类似的0.10000000149011612)

因此,数字100000000000.000010是"大",因此在小数位后变得不太准确.事实上,一旦你开始4503599627370496,你甚至不能存储所有整数!

  • 在参考"他们在基地2工作,而不是基础10":"double"使用基础`FLT_RADIX`,这是_commonly_`2`.`IEEE-754`定义了基数2和基数10.二进制格式更常见. (2认同)