2010-10-24 99 views
2

可能重复:
Why don't operations on double-precision values give expected results?四舍五入问题,双类型

我遇到一个奇怪的问题在C++中。我创建了一个Double类型的变量。然后我做了一些计算,将一些值分配给其他变量,并将结果赋给我声明的双变量。它给了我一个长小数部分的结果。我希望它只有两位小数。并将其存储到变量中。但即使经过多次尝试四舍五入,我也无法将其舍入到小数点后两位。

然后我试着另一种方法来检查真正的问题是什么。我创建了一个Double变量并将其赋值为1.11。但是当我通过放置一个断点并为该变量添加一个监视器来调试它时,我可以发现现在存储在变量中的值是1.109999999999。

我的问题是,它为什么会这样显示?我们有没有办法将变量舍入到两位小数?为什么即使我们指定一个只有两位小数的数字,它也会显示长整数的小数部分?

请建议一种方法来存储数字 - 无论是计算还是直接分配 - 按照原样存储在双变量中,而不是具有长小数部分的数字。

+2

不要使用定点计算浮点运算。 – 2010-10-24 13:57:36

+0

double d = 1.3894637; int i = ceil(d * 10); – 2015-09-16 05:37:34

回答

11

在double值的集合中,不存在数字1.11这样的事情,因为在内部,double使用二进制表示(与用于十进制表示的人类相反)。大多数有限小数(例如1.11)在二进制中具有无限表示,但由于内存有限,因为四舍五入而失去了一些精度。

与双数据类型最接近的1.11是1.1100000000000000976996261670137755572795867919921875,它在内部表示为0x3ff1c28f5c28f5c3。

您对小数点后两位的要求听起来像是您在使用金钱。一个简单的解决方案是将仙存储在一个整数(如相对于美元在双):

int cents = 111; 

这样一来,你就不会丢失任何精度。另一种解决方案是使用专用的十进制数据类型。

2

并非每个十进制数都具有精确的有限二进制浮点表示形式。你已经找到一个例子,但另一个例子是0.1(十进制)= 0.0001100110011 ...(二进制)。

您可能需要忍受这一点,或使用十进制浮点库(效率较低)。

我的建议是将数字保存为完全精确的数字,并且只有在您需要将数字显示给人类时才能进行。

+1

这取决于使用情况。金融机构对任何四舍五入错误(特别是如果它有利于客户)都不甚了解。因此,如果你用金钱做任何事情,你需要一个十进制类型。 – 2010-10-24 16:36:47

3

像float和double这样的浮点类型不是100%精确的。他们可以将14.3存储为14.299999 ...并且没有任何问题。这就是为什么你绝对不应该用==运算符来比较两个浮点数或双精度的情况下,你应该检查它们的差值的绝对值是否小于某个epsilon,比如0。现在000000001

,如果你想输出一个愉快的方式的数量,就可以使用setprecision<iomanip>

例如

#include <iostream> 
#include <iomanip> 

int main() 
{ 
    double d = 1.389040598345; 
    std::cout << setprecision(2) << d; //outputs 1.39 
} 

如果你想获得d的值四舍五入保留2位小数点后,那么你可以使用这个公式

d = floor((d*100)+0.5)/100.0; //d is now 1.39 
+2

投射到'int'是一个非常糟糕的想法,因为大多数double值太大而不适合整数集合。我建议改为调用'floor'。 – fredoverflow 2010-10-24 16:52:19

+0

@FredOverflow:好的,同意,改变 – 2010-10-24 16:53:45