ruby算术

为什么这个代码7.30 - 7.20在ruby中返回0.0999999999999996 ,而不是0.10

但是,如果我写7.30 - 7.16 ,例如,一切都会好的,我会得到0.14

问题是什么,我该如何解决?

每个计算机科学家应该知道的浮点运算

问题是我们可以很容易地用十进制写的一些数字在当前硬件实现的特定浮点格式中没有精确的表示。 说明这一点的一种随意方式是所有整数都有,但不是所有的分数,因为我们通常用2**e指数存储分数。 所以,你有3个选择:

  1. 适当地完成。 不结果的结果总是非常接近,所以圆润的结果总是“完美”。 这就是Javascript的作用,很多人甚至都没有意识到JS在浮动点上做了所有事情。

  2. 使用定点算术。 Ruby实际上让这很容易; 它是唯一一种从Fixnum无缝转换到Class Bignum的语言,因为数字越来越大。

  3. 使用旨在解决此问题的类,如BigDecimal

为了更详细地查看问题,我们可以尝试用二进制表示“7.3”。 7部分很容易,111,但我们该怎么做.3? 111.1是7.5,太大,111.01是7.25,越来越近了。 事实certificate,111.010011是“下一个最接近的较小数字”,7.296875,当我们尝试填补缺失的.003125时,我们最终发现它只是111.010011001100110011 …永远,在我们选择的有限位字符串编码中无法表示。

问题是浮点不准确 。 您可以使用Rational,BigDecimal或只是普通整数来解决它(例如,如果您想存储资金,您可以将美分数存储为int而不是美元数作为浮点数)。

BigDecimal可以准确地存储在基数10中具有有限位数的任何数字,并且舍入不包含数字的数字(因此三分之三不是一个整数)。

Rational可以准确地存储任何有理数,并且根本不能存储无理数。

这是浮点数在内存中表示的常见错误。

如果您需要确切的结果,请使用BigDecimal。

 result=BigDecimal.new("7.3")-BigDecimal("7.2") puts "%2.2f" % result 

值得注意的是,在一个基数中具有少量小数的数字通常在另一个基数中具有非常大的小数。 例如,在基数10中表示1/3(= 0.3333 …)需要无限小数,但在基数3中只需要一个小数。同样,需要多个小数来表示数字1/10(在基地2中= 0.1)。

由于您正在进行浮点数学运算,因此返回的数字是您的计算机用于精确度的数字。

如果你想要一个更接近的答案,一个设定的精度,只需多次浮动(例如100),将其转换为int,做数学,然后除。

还有其他解决方案,但我发现这是最简单的,因为对我来说舍入似乎总是有些不确定。

在此之前已经提到过这个问题,您可能想要寻找之前给出的一些答案,例如: 解决浮点数中的精度问题