有没有人在ruby中解决这个问题:
我们说:a = 8.1999999
我们希望将其舍入2位小数,即8.20,然后乘以1,000,000,变为8,200,000
我们这样做;
(a.round(2) * 1000000).to_i
但我们得到的是8199999,为什么?
事情是,如果我们乘以1000,100000或10000000而不是1000000,我们得到了正确的结果。任何人都知道为什么?
我们正在使用ruby 1.9.2并尝试使用1.9.3。
谢谢!
答案 0 :(得分:8)
每当你在计算中得到时髦的数字时使用bigdecimal
require 'bigdecimal'
a = BigDecimal(8.1999999.to_s)
(a.round(2) * 1000000).to_i
答案 1 :(得分:3)
因为a.round(2)返回浮点数,因此计算不完美。
要获得正确的结果,请尝试以下操作:(10 * a).round.to_i * 100000
答案 2 :(得分:0)
在某种意义上,您的初始舍入 正在工作, 1 。问题是8.2没有精确的内部表示。如果您只需将8.2
输入到irb中或显示#round(2)
方法调用的结果,那么看起来就像您有8.2但不是。实际存储的数字略小于8.2。
您最终会被输出舍入逻辑的默认值所击败。一旦内部略小于8.2位被加倍,错误就会转移到数字的整数部分,除非你要求,否则这部分不会被舍入。你可以这样做:(a * 1000000).round
问题是我们用十进制编写数字但是将它们存储在二进制中。这适用于整数;但它的分数很差。
事实上,我们编写的大多数小数部分无法准确表示。
每个机器分数是x / 2 n 形式的有理数。现在,常数是十进制的,每个十进制常数是x /(2 n * 5 m )形式的有理数。 5 m 数字是奇数,因此对于它们中的任何一个都没有2 n 因子。只有当 m == 0 时,分数的二进制和十进制扩展都有一个有限的表示。因此,1.25是准确的,因为它是5 /(2 2 * 5 0 )但0.1不是因为它是1 /(2 0 * 5 1 )。实际上,在1.01 .. 1.99系列中,只有3个数字可以表示:1.25,1.50和1.75。
因为8.2没有精确的表示,所以它永远以二进制形式重复,从未完全相加到8.2。它继续无限为1100110011 ...
1。但请注意,您可能需要a.round(1)
而不是2. #round
的参数是您想要的分数位数,而不是重要数数字。在这种情况下,结果是相同的,并不重要。