浮点分辨率似乎比应该

时间:2016-01-28 17:48:19

标签: c++ floating-point rounding-error

当简单地指定仅包含4个有效数字的浮点值时,我看到了一些错误。我写了一个简短的程序来调试,我不明白问题是什么。在我的平台上验证浮点数的限制之后似乎应该没有任何错误。造成这种情况的原因是什么?

#include <stdlib.h>
#include <stdio.h>
#include <limits>
#include <iostream>

int main(){

  printf("float size: %lu\n", sizeof(float));
  printf("float max: %e\n", std::numeric_limits<float>::max());
  printf("float significant figures: %i\n", std::numeric_limits<float>::digits10);

  float a = 760.5e6;
  printf("%.9f\n", a);
  std::cout.precision(9);
  std::cout << a << std::endl;

  double b = 760.5e6;
  printf("%.9f\n", b);
  std::cout << b << std::endl;

  return 0;
}

输出:

float size: 4
float max: 3.402823e+38
float significant figures: 6
760499968.000000000
760499968
760500000.000000000
760500000

4 个答案:

答案 0 :(得分:3)

float具有24位精度,大致相当于7位十进制数。 double具有53位精度,大致相当于16位十进制数。

正如评论中所述,760.5e6无法完全代表float;但是,它double完全可以表示。这就是为什么double的打印结果是准确的,而float的打印结果不是。

请求打印比您的浮点数可表示的更多十进制数字是合法的。您报告的结果不是错误 - 它们只是十进制打印算法尽力而为的结果。

答案 1 :(得分:1)

float中存储的数字是760499968.这是IEEE 754 binary32浮点数的预期行为,通常为float

IEEE 754浮点数分为三部分:符号位,指数和尾数。由于所有这些值都存储为,因此得到的数字排序科学计数法的二进制等价物。尾数位比二进制科学符号中的有效数字允许的二进制数字少一个。

就像十进制科学数字一样,如果指数超过有效数字,你将失去整数精度。

这个类比只延伸到目前为止:尾数是对您可能熟悉的十进制科学符号中的系数的修改,并且在标准中存在某些具有特殊含义的位模式。

这种存储机制的最终结果是整数760500000不能由IEEE 754 binary32用其23位尾数精确表示:它在2^(mantissa_bits + 1)的整数后失去整数级精度,对于23位尾数浮点数是16777217。可以用浮点数表示的最接近76050000的整数是760499968和76050032,由于round-ties-to-even rule而选择前者用于表示,并且以比浮点数更高的精度打印整数。自然会导致明显的不准确。

答案 2 :(得分:0)

一个double,在你的情况下有64位大小,自然比浮点数更精确,在你的情况下是32位。因此,这是预期的结果

规范并未强制任何类型应正确表示所有小于std :: numeric_limits :: max()的数字及其精度。

答案 3 :(得分:0)

您显示的数字仅在第8位和之后关闭。对于float,保证准确度在6位数内。如果您只打印了6位数字,输出将四舍五入,您将看到您期望的值。

printf("%0.6g\n", a);

请参阅http://ideone.com/ZiHYuT