为什么 Ruby 在计算 mod 时要添加 precision/digits?
Why is Ruby adding precision/digits when calculating a mod?
我需要用坐标做一些计算,遇到了
这种(至少对我而言)奇怪的行为。
有人可以解释为什么会这样吗?
$ long
=> 49.0126760222489
$ long % long.floor
=> 0.012676022248896857
我原以为最后一行的计算结果只是句点后的数字,从 long
开始,但最后一行却多了一个 6857
。
为什么要加数字?
信息来自哪里?
似乎与Ruby本身无关,但是:
floating point numbers that in general suffer from this type of rounding error, because they’re limited to x number of bytes, and, in general, cannot store decimal number perfectly.
从上面的文档中,您还可以获得一些绕过本机浮动行为的选项。上面的文档可以被认为是官方文档,因为它是由 ruby-doc.org.
提供的
我想我们只是看到了 float 的错误。参见 0.0126760222489 % 1.0
和 1.0126760222489 % 1.0
。你认为结果应该是相同的,但不是 - IEEE754 floats/doubles 不保证 运行 完美的结果,默认情况下这些在 Ruby 中用于存储浮点值.
甚至有点表现出来in the docs
6543.21.modulo(137) #=> 104.21
6543.21.modulo(137.24) #=> 92.9299999999996
可以看到第二个结果有一点误差。实际上,在 Ruby 2.3.1 我 运行 第一行得到:
pry(main)> 6543.21.modulo(137)
=> 104.21000000000004
与取模没有必然关系,也不一定可见:
[30] pry(main)> 10.0126760222489 - 0.0
=> 10.0126760222489
[31] pry(main)> 10.0126760222489 - 1.0
=> 9.0126760222489
[32] pry(main)> 10.0126760222489 - 2.0
=> 8.0126760222489
[33] pry(main)> 10.0126760222489 - 3.0
=> 7.0126760222489
[34] pry(main)> 10.0126760222489 - 4.0
=> 6.0126760222489
[35] pry(main)> 10.0126760222489 - 5.0
=> 5.0126760222489
[36] pry(main)> 10.0126760222489 - 6.0
=> 4.0126760222489
[37] pry(main)> 10.0126760222489 - 7.0
=> 3.0126760222489004
每个使用标准浮点数的软件都需要考虑这些小错误。如果由于某种原因您无法处理,那么您可以使用 bigdecimal
(应该已经包含在您的 Ruby 中)、定点或一些类似的数字库
require 'bigdecimal'
BigDecimal('6543.21').modulo(137).to_s
=> "0.10421E3"
BigDecimal('6543.21').modulo(137).to_f
=> 104.21
请记住,'bigdecimal' 可能会更慢并且可能会占用更多内存。
我需要用坐标做一些计算,遇到了 这种(至少对我而言)奇怪的行为。 有人可以解释为什么会这样吗?
$ long
=> 49.0126760222489
$ long % long.floor
=> 0.012676022248896857
我原以为最后一行的计算结果只是句点后的数字,从 long
开始,但最后一行却多了一个 6857
。
为什么要加数字?
信息来自哪里?
似乎与Ruby本身无关,但是:
floating point numbers that in general suffer from this type of rounding error, because they’re limited to x number of bytes, and, in general, cannot store decimal number perfectly.
从上面的文档中,您还可以获得一些绕过本机浮动行为的选项。上面的文档可以被认为是官方文档,因为它是由 ruby-doc.org.
提供的我想我们只是看到了 float 的错误。参见 0.0126760222489 % 1.0
和 1.0126760222489 % 1.0
。你认为结果应该是相同的,但不是 - IEEE754 floats/doubles 不保证 运行 完美的结果,默认情况下这些在 Ruby 中用于存储浮点值.
甚至有点表现出来in the docs
6543.21.modulo(137) #=> 104.21
6543.21.modulo(137.24) #=> 92.9299999999996
可以看到第二个结果有一点误差。实际上,在 Ruby 2.3.1 我 运行 第一行得到:
pry(main)> 6543.21.modulo(137)
=> 104.21000000000004
与取模没有必然关系,也不一定可见:
[30] pry(main)> 10.0126760222489 - 0.0
=> 10.0126760222489
[31] pry(main)> 10.0126760222489 - 1.0
=> 9.0126760222489
[32] pry(main)> 10.0126760222489 - 2.0
=> 8.0126760222489
[33] pry(main)> 10.0126760222489 - 3.0
=> 7.0126760222489
[34] pry(main)> 10.0126760222489 - 4.0
=> 6.0126760222489
[35] pry(main)> 10.0126760222489 - 5.0
=> 5.0126760222489
[36] pry(main)> 10.0126760222489 - 6.0
=> 4.0126760222489
[37] pry(main)> 10.0126760222489 - 7.0
=> 3.0126760222489004
每个使用标准浮点数的软件都需要考虑这些小错误。如果由于某种原因您无法处理,那么您可以使用 bigdecimal
(应该已经包含在您的 Ruby 中)、定点或一些类似的数字库
require 'bigdecimal'
BigDecimal('6543.21').modulo(137).to_s
=> "0.10421E3"
BigDecimal('6543.21').modulo(137).to_f
=> 104.21
请记住,'bigdecimal' 可能会更慢并且可能会占用更多内存。