C++ 不截断双精度?

C++ not truncating doubles?

提问人:Bunny 提问时间:10/9/2018 最后编辑:Jonathan LefflerBunny 更新时间:10/9/2018 访问量:178

问:

我的代码

运行以下代码的结果:

#include <cstdio>

//i define printBits elsewhere but that's not relevant to my question
void printBits(const float f);
void printBits(const double f);

int main(int argc, char **argv) {
  float f=4.2;
  double d=4.2;
  printf("float: %20.20f\n",f);
  printBits(f);
  printf("double: %50.50f\n",d);
  printBits(d);

 return 0;
}

是:

float: 4.19999980926513671875
0    10000001 00001100110011001100110

double: 4.20000000000000017763568394002504646778106689453125
0 10000000001 0000110011001100110011001100110011001100110011001101

请注意,我如何将 和 都设置为 4.2,但浮点值略小于 4.2,double 值略大于 4.2。我明白为什么浮点值小于 4.2;4.2 值被截断为小于 4.2 的值 ~2^-21。但是,我不明白为什么双精度值略大于 4.2。我以为浮点数和双精度值只会截断,但似乎双精度值是向上舍入而不是向下舍入。fd

一般来说,浮点数和双精度是否四舍五入到最接近的可表示值?浮动和双打的圆度不同吗?我尝试搜索这个,但找不到任何相关的东西。

C++ 浮点精度

评论

0赞 Jonathan Leffler 10/9/2018
如果包括 ,则使用的是 C++,而不是 C。此外,如果你有重载的函数,你肯定是在用 C++ 而不是 C 工作,不要用错误的语言标记——这会惹恼人们并导致反对票。<cstdio>
1赞 Retired Ninja 10/9/2018
希望有人会来解释 4.2 如何不能完全表示为二进制浮点,但这就是原因。stackoverflow.com/questions/588004/......
2赞 Jonathan Leffler 10/9/2018
SO上有一个标准的交叉引用问答——浮点数学坏了吗?答案是否定的,但它不一定像你期望的那样工作。

答:

6赞 Mark Ransom 10/9/2018 #1

浮点值不会被截断,而是会四舍五入到最接近的可表示值。您发现了一个有趣的示例,其中舍入的方向不同,具体取决于浮点的大小,但这种情况并不少见;您可以预期舍入在大约 50% 的时间内上升,在 50% 的时间内下降,少数值是完全可表示的,根本不是舍入的。例如,4.25 是确切的。

评论

2赞 Eric Postpischil 10/9/2018
我认为易于可视化的示例可能很有用。例如,如果可以表示 0、1/4、1/2、3/4 和 1,并且可以表示 0、1/8、1/4、3/8、1/2、5/8、3/4、7/8 和 1,则将 .6 转换为将向下舍入为 1/2(更接近 .5 而不是 .75),但将 .6 转换为将向上舍入为 5/8(更接近 .625 而不是 .5)。floatdoublefloatdouble