【问题标题】:Best way to correct the modulus error in R?纠正R中模数误差的最佳方法?
【发布时间】:2018-05-17 01:11:25
【问题描述】:

核心 R 引擎在表示模运算输出的方式上存在严重缺陷:

ceiling((1.99 %% 1) * 100)

返回:99(正确)

ceiling((2.99 %% 1) * 100)

返回:100(不正确)

该行为将表现为任何整数值 N + 2.99(例如 3.99 等)。如果这与浮点表示相关联,则系统不会表达差异的全部细节。这尤其令人不安,因为:

(1.99 %% 1)(2.99 %% 1)似乎都返回 0.99。

((1.99 %% 1) * 100)((2.99 %% 1) * 100)似乎都返回 99。

但是,如果您进行任何舍入或类似的数学运算,2.99 的 invisible 残差值会以意想不到的方式翻转。

虽然为我当前的应用程序解决这个问题是微不足道的:

floor((2.99 - floor(2.99)) * 100)

返回:99(正确)

sprintf("%.22f", floor((2.99 - floor(2.99)) * 100))

返回:99.0000000000000000000000(正确)

...我想知道 Modulus 还有多少其他实例返回错误值而没有显示浮点增量的基础细节。有没有办法暴露 Modulus 似乎附加的潜在剩余价值?否则它是不可见的。

编辑:根据下面 andrew.punnett 的慷慨示例,print(1.99, digits = 22) 返回 1.99(无浮点扩展),而 print(1.99 %% 1, digits = 22) 返回 0.98999999999999999。根据 Aaron 的敏锐眼光,这似乎取决于版本和/或系统。

谢谢!

【问题讨论】:

  • 嗨,欢迎来到 StackOverflow!我担心您的第一次体验会很糟糕,因此会建议对您的问题进行一些编辑以阻止其中一些问题,并帮助您获得更好的答案。 1)有些人会假设您对浮点错误一无所知并居高临下地解释;所以我建议你编辑包括这可能是一个潜在的原因,你想知道如何更好地处理这个 2)有些人会因为指出“错误/缺陷”而生气,再次可能指向浮点问题;我建议您改写为“行为”。最美好的祝愿!
  • 似乎还有一些系统特定的事情正在发生;对于print(1.99, digits = 22) 我得到1.989999999999999991118
  • 谢谢亚伦!我惊呆了(哈哈)1.99 的跨版本扩展存在差异——这真的很奇怪。但是非常感谢二进制表示链接!我可能会在不久的将来使用它。
  • 可能的答案here as well

标签: r modulus


【解决方案1】:

这并不是R 中的真正错误。确实是floating-point arithmetic的属性。

出现问题是因为 1.99 或 2.99 都不能精确地表示为浮点数。可以存储在双精度(64 位)浮点数中的最接近 2.99 的十进制数是 2.99000000000000021316282072803 (try the conversion here)

因此表达式计算为:

ceiling((2.99 %% 1) * 100) = ceiling(99.000000000000021316282072803)
                           = 100

相比之下,最接近 1.99 的表示是 1.989999999999999991118215803,它恰好给出了您期望的答案:

ceiling((1.99 %% 1) * 100) = ceiling(98.9999999999999991118215803)
                           = 99

对于 IEEE 754 浮点运算,这两个结果都是正确的,但正如您所见,只有一个结果与应用实数运算规则得到的结果一致。

R 中的默认行为是截断 print() 中的每个浮点数,这一事实使这个问题更加复杂。如果你想看到更多的数字,那么你必须提供一个digits 参数:

print(1.99, digits = 22)

但是,即使这样也不能在所有平台上为您提供正确的位数,因此准确查看浮点数的更可靠方法是:

cat(sprintf("%.22f\n", 1.99))

【讨论】:

  • 我认为@andrew.punnett 的意思是,R 确实 返回了那个;它只是不显示它。
  • 我也觉得这很烦人。事实上,如果你尝试使用命令print(1.99, digits = 22),你会看到 R 坚持这个数字实际上是 1.99。我不知道为什么
  • 附言。很好的答案,清晰但不居高临下。 :) 谢谢。
  • 似乎还有一些特定于系统的事情正在发生;对于print(1.99, digits = 22),我得到1.989999999999999991118
  • 感谢您的信息。我用 sprintf("%.21e", 1.99) 得到了这个结果,但由于某种原因使用 print() 时没有。
猜你喜欢
  • 2020-01-23
  • 2021-09-24
  • 2022-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-27
  • 2010-10-17
  • 1970-01-01
相关资源
最近更新 更多