【问题标题】:Why is Ruby adding precision/digits when calculating a mod? [duplicate]为什么 Ruby 在计算 mod 时会添加精度/数字? [复制]
【发布时间】:2017-02-13 23:14:53
【问题描述】:

我需要用坐标进行一些计算并遇到 这种(至少对我而言)奇怪的行为。 有人可以解释为什么会这样吗?

$ long
=> 49.0126760222489
$ long % long.floor
=> 0.012676022248896857

我原本希望最后一行仅计算句点后的数字,从 long 开始,但在末尾添加了一个额外的 6857

为什么要添加数字?

信息从何而来?

【问题讨论】:

  • long的值是怎么计算出来的?
  • 来自数据库
  • 您使用的是哪个版本的 Ruby?
  • 这是浮点数学无处不在的人工制品。完全相同的效果可以显示在例如Python 和 Javascript。与较大的数字相比,较小的数字可以以更高的精度表示。
  • 请注意,差异在microns 的范围内(假设这些是地面坐标)

标签: ruby geo


【解决方案1】:

好像和Ruby本身没什么关系,但是:

浮点数通常会遭受这种类型的舍入错误,因为它们被限制为 x 字节数,并且通常不能完美地存储十进制数。

Documentation

从上面的文档中,还可以获得一些解决本机浮动行为的选项。以上文档可以被视为官方文档,由ruby-doc.org提供。

【讨论】:

  • 这不是一个“更精确”的结果,这是一个不太精确的结果。如果它在末尾添加0000 会更精确,添加6857 只会使结果错误小幅度。
  • 转换long.floor Fixnum 值似乎与我无关,因为long 本身已经是浮点数。我发现 float%fixnum 没有意外导致浮动。我想我们只是看到了 float 的错误。参见 0.0126760222489 % 1.01.0126760222489 % 1.0
【解决方案2】:

我想我们只是看到了 float 的错误。参见 0.0126760222489 % 1.01.0126760222489 % 1.0。您可能认为结果应该是相同的,但不是 - IEEE754 浮点数/双精度数并不能保证完美的结果,默认情况下它们在 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”可能会更慢,并且可能会使用更多内存。

【讨论】:

  • 很好,感谢您的回答,尽管之前有人问过(并回答过)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-10
  • 1970-01-01
  • 2021-05-31
  • 2015-05-05
  • 1970-01-01
  • 2017-04-12
  • 2021-12-10
相关资源
最近更新 更多