我是计算机工程专业的学生,并为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有关,因此当它被转换时会被"截断",但我不确定.
如果你们中的任何一个人想要解释所有这些"下面"的内容,我会发现它很有趣!
问题是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).计算后的舍入行为并未真正定义.
实际上,浮点数的操作并没有精确指定,这意味着您可以在不同的机器上遇到不同的结果.这样就可以实现性能调整,导致稍微不正确的结果,即使不涉及舍入!情况可能是在另一台机器上你得到了预期的结果,而在其他机器上却没有.