【问题标题】:Issue with precision of Ruby math operationsRuby数学运算的精度问题
【发布时间】:2010-09-23 09:46:21
【问题描述】:

您知道如何解决以下数学精度问题吗?

p RUBY_VERSION # => "1.9.1"
p 0.1%1 # => 0.1
p 1.1%1 # => 0.1
p 90.0%1 # => 0.0
p 90.1%1 # => 0.0999999999999943
p 900.1%1 # => 0.100000000000023

p RUBY_VERSION # => "1.9.2"
p 0.1%1 # => 0.1
p 1.1%1 # => 0.10000000000000009
p 90.0%1 # => 0.0
p 90.1%1 # => 0.09999999999999432
p 900.1%1 # => 0.10000000000002274

【问题讨论】:

标签: ruby math rounding precision


【解决方案1】:

大十进制


正如man 所说;

将无限多个实数压缩为有限位数需要近似表示。


然而,我使用BigDecimal 类取得了巨大的成功。引用它的介绍

Ruby 提供了对任意精度整数运算的内置支持。例如:

42**13 -> 1265437718438866624512

BigDecimal 为非常大或非常精确的浮点数提供类似的支持。


举一个你的例子;

>> x = BigDecimal.new('900.1')
=> #<BigDecimal:101113be8,'0.9001E3',8(8)>
>> x % 1
=> #<BigDecimal:10110b498,'0.1E0',4(16)>
>> y = x % 1
=> #<BigDecimal:101104760,'0.1E0',4(16)>
>> y.to_s
=> "0.1E0"
>> y.to_f
=> 0.1


如您所见,确保不错的精度是可能的,但需要付出一些努力。

【讨论】:

  • 注意!您不仅仅是在增加精度:您正在为十进制数字选择更好的表示形式。 1/3 仍会四舍五入。
  • @xtofl - 这是一个公平的观点,但我希望关于“近似表示”的引用能够触及它。
【解决方案2】:

这适用于所有计算机语言,而不仅仅是 Ruby。这是在二进制计算机上表示浮点数的一个特性:

What Every Computer Scientist Should Know About Floating Point Arithmetic

【讨论】:

    【解决方案3】:

    0.1 写入浮点总是会导致舍入错误。如果你想要“精确”的十进制表示,你应该使用Decimal type

    【讨论】:

    • 我在PHP 没有注意到这样的问题。 Ruby 默认没有“'精确'十进制表示”有什么好的理由吗?
    • PHP 也有同样的问题,因为它与语言无关:php.net/manual/en/language.types.float.php
    猜你喜欢
    • 2020-04-29
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 2021-07-27
    • 1970-01-01
    • 2011-02-21
    • 1970-01-01
    • 2011-07-22
    相关资源
    最近更新 更多