Ruby on rails 十进制数的Ruby舍入和格式化

Ruby on rails 十进制数的Ruby舍入和格式化,ruby-on-rails,ruby,floating-point,rounding,Ruby On Rails,Ruby,Floating Point,Rounding,我已经看完了:而且 我的问题是,当我使用ruby对浮点数进行取整和格式化时,结果仍然与手工计算的结果不同。下面是一个例子: 编辑2 [28] pry(main)> ##################################### [29] pry(main)> # test one [30] pry(main)> ##################################### [31] pry(main)> foo = (6.0135 * (6500

我已经看完了:而且

我的问题是,当我使用ruby对浮点数进行取整和格式化时,结果仍然与手工计算的结果不同。下面是一个例子:

编辑2

[28] pry(main)> #####################################
[29] pry(main)> # test one
[30] pry(main)> #####################################
[31] pry(main)> foo = (6.0135 * (650000 / 1000)) 
             => 3908.7749999999996
[32] pry(main)> foo = '%.2f' % foo.round(2)
             => "3908.77"
[33] pry(main)> # should be 3908.78

[36] pry(main)> #####################################
[37] pry(main)> # test two
[38] pry(main)> #####################################
[39] pry(main)> foo = 650000 / 1000
             => 650
[40] pry(main)> foo = foo * 6.0135
             => 3908.7749999999996
[41] pry(main)> foo = '%.2f' % foo.round(2) # should be 3908.78
             => "3908.77"

[44] pry(main)> #####################################
[45] pry(main)> # test three 
[46] pry(main)> #####################################
[47] pry(main)> foo = 650000 / 1000
             => 650
[48] pry(main)> foo = foo * 6.0135
             => 3908.7749999999996
[49] pry(main)> foo = foo.round(2) # should be 3908.78
=> 3908.77

[52] pry(main)> #####################################
[53] pry(main)> # test four - The result of test four is expected
[54] pry(main)> #####################################
[55] pry(main)> foo = 650000 / 1000
             => 650
[56] pry(main)> foo = foo * 6.0135
             => 3908.7749999999996
[57] pry(main)> foo = '%.2f' % foo
             => "3908.77"

[58] pry(main)> #####################################
[59] pry(main)> # test five
[60] pry(main)> #####################################
[61] pry(main)> foo = 650000 / 1000
             => 650
[62] pry(main)> foo = foo * 6.0135
             => 3908.7749999999996
[63] pry(main)> foo = foo.round(5) 
             => 3908.775
测试1:这是我在我的库中使用的正常公式,它给了我这个问题

测试2:我的想法是,可能在一个作业中同时做两个操作会导致一些问题

测试3:既然大家都知道,
“%.2f”%
会导致一些舍入问题,它会截断某些内容,那么这可能就是问题所在

测试4:既然
'%.2f%
不是问题所在,可能是
.round(2)
导致了问题

编辑2: 测试5:如果我展开该轮正在查看的数字,我会得到一个可以使用的数字(即,再次对该数字进行第(2)轮)。但这似乎是一个不可靠的解决方案,适用于有限的情况,而不是一般情况

我真的不在乎浮点是不准确的。我的问题是如何正确地将这个数字四舍五入,以便得到正确的答案(如果您手工操作,您将得到正确的答案)

此外,一般来说,是否有最佳的四舍五入做法来纠正给药点错误?我知道用两个整数来表示浮点数是很困难的,但这似乎很麻烦

多谢各位

编辑1


如果您使用
.round(5)
而不是
.round(2)
将答案与应该的答案进行比较,您会得到更合理的答案。增加一轮中的数字有什么缺点吗?

'%.2f%
-截断数字并无法正确进行四轮

.round(2)
-找不到足够的小数位,无法正确地返回到四舍五入。所以,如果你把数字放在大于2的范围内,四舍五入的问题就不存在了

编辑1

根据IEEE标准,有5种方法可对数字进行四舍五入:

  • 到最近,关系到甚至
  • 至最近,系紧距离为零
  • 接近0
  • 朝向+∞
  • 朝向−∞
    在这种情况下,与其说我是如何舍入的,不如说是需要考虑小数点后的位数。通常,一个人需要担心精确度。由于此错误是由计算机造成的,因此我假设增加小数点后的数值会更好、更准确。

    我在Rails控制台上对其进行了测试,没有发现任何奇怪的行为:

    >> foo = 650000 / 1000
    => 650
    >> foo = foo * 6.0135
    => 3908.7749999999996
    >> foo.round(2)
    => 3908.77
    >> foo.round(3)
    => 3908.775
    >> foo.round(5)
    => 3908.775
    >> afoo = '%.2f' % foo
    => "3908.77"
    >> afoo = '%.5f' % foo
    => "3908.77500"
    
    3908.7749999996小于3908.775,如果使用,将向下舍入为3908.77。舍入(2)。
    .3908.775中预期的四舍五入结果,也可以使用谷歌计算器进行复制。你为什么认为这是不正确的?我很想了解这一点。

    round
    按预期工作。你得到了错误的结果,因为你的输入已经有缺陷了。浮点数
    6.0135
    实际上是:

    6.01349999999999962341235004714690148830413818359375
    
    将此数字乘以
    650
    会使错误更严重。您得到的结果更接近于
    3908.77
    ,而不是
    3908.78

    foo = 6.0135 * 650
    #=> 3908.7749999999996
    
    (foo - 3908.77).abs
    #=> 0.004999999999654392
    
    (foo - 3908.78).abs
    #=> 0.005000000000563887
    
    要获得正确的结果,您可以使用以下方法:

    foo = (6.0135 * 10000).round  * 0.065
    #=> 3908.775
    
    foo.round(2)
    #=> 3908.78
    
    或者,您可以首先使用
    BigDecimal
    来避免浮点错误:

    require 'bigdecimal'
    foo = BigDecimal('6.0135') * 650
    foo.to_s('F')
    #=> "3908.775"
    
    foo.round(2).to_s('F')
    #=> "3908.78"
    

    为什么投反对票?这一轮是正确的。3908.77499999.. 将始终为3908.77,因为它确实小于3908.775。你总是对总值进行四舍五入,而不是从最后一个数字开始四舍五入,然后再继续……除了实际答案应该是3908.78这一事实之外。如果你使用
    .round(5)
    你会得到3908.78更清楚地说,否决票不是我的,但诚实地说,在.round(2)中应该是3908.77。和.round(5)应该为您提供3908.775,并且在我的rails控制台中也是如此。请发布您遇到问题的代码。不是代码的图片,而是代码。我想你需要引用IEEE浮点标准来证明这些陈述的合理性,然后才能作为答案。是的@muistooshort和lukasz,我实际上对如何“解决”这个问题有了第二个想法。这给了我这个具体案例的答案。这样做还有其他问题吗?谢谢。除了一些性能上的影响之外,是否还有一些重大的倒退?我打算对每个请求进行25次这种计算,这种更改会对请求的性能产生很大影响吗?@alex_milhouse Rails中的请求-响应周期并不是那么轻量级的。如果25次计算会对它产生显著影响,我会感到惊讶。太好了。谢谢,这正是我需要的。