为什么我的BigDecimal对象初始化有意外的舍入错误? [英] Why are my BigDecimal objects initialized with unexpected rounding errors?
问题描述
BigDecimal.new(34.13985572755337,9)
code>
等于 34.0
但是
BigDecimal.new(34.13985572755338,9)
等于 34.1398557
?
请注意,我在64位机器上运行这个。
用字符串初始化而不是浮动
用Floats无法获得可靠的行为。你犯的错误是用Float值而不是String值来初始化你的BigDecimals,这在一开始就引入了一些不准确的地方。例如,在我的64位系统上:
float1 = 34.13985572755337
float2 = 34.13985572755338
#如果你的Float不能正确地
#表示,你也可以在这里使用字符串文字。例如:
#
#BigDecimal.new(34.13985572755337,9)
#
#会更安全,但是Float#to_s可以和提供的语料一起工作。
bd1 = BigDecimal.new(float1.to_s,9)
bd2 = BigDecimal.new(float2.to_s,9)
bd1.to_s
#=> ; 0.3413985572755337E2
bd2.to_s
#=> 0.3413985572755338E2
bd1.to_f == float1
#=> true
bd2.to_f == float2
#=>真正的
这是争论的内部表示很重要的情况之一。因此,您的里程将根据初始化对象的方式而有所不同。
In Ruby 2.2.0, why does:
BigDecimal.new(34.13985572755337, 9)
equal 34.0
but
BigDecimal.new(34.13985572755338, 9)
equal 34.1398557
?
Note that I am running this on a 64 bit machine.
Initialize with Strings Instead of Floats
In general, you can't get reliable behavior with Floats. You're making the mistake of initializing your BigDecimals with Float values instead of String values, which introduces some imprecision right at the beginning. For example, on my 64-bit system:
float1 = 34.13985572755337
float2 = 34.13985572755338
# You can use string literals here, too, if your Float can't be properly
# represented. For example:
#
# BigDecimal.new("34.13985572755337", 9)
#
# would be safer, but Float#to_s works fine with the provided corpus.
bd1 = BigDecimal.new(float1.to_s, 9)
bd2 = BigDecimal.new(float2.to_s, 9)
bd1.to_s
#=> "0.3413985572755337E2"
bd2.to_s
#=> "0.3413985572755338E2"
bd1.to_f == float1
#=> true
bd2.to_f == float2
#=> true
This is one of those cases where the internal representation of the arguments matter. Therefore, your mileage will vary depending on how you initialize your object.
这篇关于为什么我的BigDecimal对象初始化有意外的舍入错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!