浮动到Ints的精度与双打到Ints的精确度,出乎意料的结果

njf*_*ife 4 c++ casting

我是计算机工程专业的学生,​​并为BYU-Idaho的入门C++课程做辅导,一名学生成功地让我难过.

如果为此编写代码:

#include <iostream>
using namespace std;
int main()
{
   float y = .59;
   int x = (int)(y * 100.0);
   cout << x << endl;
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

结果= 58

#include <iostream>
using namespace std;
int main()
{
   double y = .59;
   int x = (int)(y * 100.0);
   cout << x << endl;
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

结果= 59

我告诉他这是一个精确的问题,因为int比浮子更精确,它会丢失信息.双精度比浮点精确,所以它的工作原理.

但是我不确定我所说的是否正确.我认为这与使用零填充的int有关,因此当它被转换时会被"截断",但我不确定.

如果你们中的任何一个人想要解释所有这些"下面"的内容,我会发现它很有趣!

lee*_*mes 7

问题是float不够准确,不能保持精确值0.59.如果存储这样的值,它将以二进制表示(已在编译期间)舍入为不同的值,在您的情况下,这是一个略小于0.59的值(它可能稍微大于您希望它的值) ).将此值乘以100时,得到的值略小于59.将此值转换为整数会将其舍入为0,因此这将导致58.

作为浮点数的0.59将被存储为(现在表示为人类可读的十进制数):

0.589999973773956298828125
Run Code Online (Sandbox Code Playgroud)

现在到了double类型.虽然这种类型具有基本相同的问题,但可能有两个原因导致您获得预期结果:两者double都可以保存您想要的确切值(这不是0.59的情况,但对于其他值可能是这种情况),或者编译器决定详谈.因此,将其乘以100会导致一个小于59 的值,并且如预期的那样将四舍五入为0到59.

现在请注意,double编译器仍然可以将0.59作为a 进行舍入.的确,我刚刚检查过它.0.59作为a double将被存储为:

0.58999999999999996891375531049561686813831329345703
Run Code Online (Sandbox Code Playgroud)

但是,在将此值转换为整数之前,您将此值乘以100 .现在有来自一个有趣的问题:当用100倍的差别y由编译器把0.59的消除,因为0.59*100可再次无法精确存储.事实上,处理器计算0.58999999999999996891375531049561686813831329345703 * 100.0,这将四舍五入最多至59,其中一些可以在来表示double!

有关详细信息,请参阅此代码:http://ideone.com/V0essb

现在你可能想知道为什么不相同float,它应该表现完全相同但精度不同.问题是,0.589999973773956298828125 * 100.0舍入到59(其也可以在表示float).计算后的舍入行为并未真正定义.

实际上,浮点数的操作并没有精确指定,这意味着您可以在不同的机器上遇到不同的结果.这样就可以实现性能调整,导致稍微不正确的结果,即使不涉及舍入!情况可能是在另一台机器上你得到了预期的结果,而在其他机器上却没有.