为什么snprintf更改输出字符串? [英] Why snprintf changes output string?

查看:146
本文介绍了为什么snprintf更改输出字符串?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用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浮点数的问题,但我将在这里总结相关的几点:


  1. double 和family以有限的精度有效地以科学记数法存储数字。这意味着数字越大,准确度越低。
  2. 大多数数字都使用基数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:

  1. double and family effectively store numbers in scientific notation with limited precision. This means the larger the number, the less accurate it'll be.
  2. Most numbers use base 2. As such, the decimal 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!

这篇关于为什么snprintf更改输出字符串?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆