Ruby 为什么我的BigDecimal对象初始化时出现意外的舍入错误?

Ruby 为什么我的BigDecimal对象初始化时出现意外的舍入错误?,ruby,floating-point,rounding,bigdecimal,floating-point-precision,Ruby,Floating Point,Rounding,Bigdecimal,Floating Point Precision,在Ruby 2.2.0中,为什么: BigDecimal.new(34.13985572755337, 9) 相等34.0但 BigDecimal.new(34.13985572755338, 9) 是否等于34.1398557 请注意,我是在64位机器上运行的 用字符串而不是浮点数初始化 一般来说,使用浮动无法获得可靠的行为。你犯了用浮点值而不是字符串值初始化大小数的错误,这在一开始就引入了一些不精确性。例如,在我的64位系统上: float1 = 34.13985572755337 fl

在Ruby 2.2.0中,为什么:

BigDecimal.new(34.13985572755337, 9)
相等
34.0

BigDecimal.new(34.13985572755338, 9)
是否等于
34.1398557

请注意,我是在64位机器上运行的

用字符串而不是浮点数初始化 一般来说,使用浮动无法获得可靠的行为。你犯了用浮点值而不是字符串值初始化大小数的错误,这在一开始就引入了一些不精确性。例如,在我的64位系统上:

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

这是论点的内部表达很重要的一种情况。因此,您的里程数将根据您初始化对象的方式而有所不同。

BigDecimal.new(34.13985572755337,9)。在我的系统上返回
34.1398557
。我遇到了相同的问题。我猜这取决于体系结构,我的系统是32位的,所以我想这就是我得到舍入误差的地方。有趣的是,
BigDecimal.new('34.13985572755337',9)
当我这样做时,效果非常好。@hakcho嗯,字符串没有舍入问题;-)有趣的是,我在Ruby 2.1.x和2.2.x上得到了
34.0
,在Ruby 2.0.x和1.9.x上得到了
34.1398557
。这个问题与使用FLOAT或RATIONAL时的BigDecimal初始化方法有关。此行为从数字32开始(31及之前的数字已更正)
BigDecimal.new('32.13985572755337',9)
如果传递字符串,则此问题不会出现
BigDecimal.new(“34.13985572755337”)
。我想你可以在抱歉的情况下就此提出问题,但这甚至不能回答问题。Ruby可以存储一个浮点值
34.13985572755337
很好,问题是在BigDecimal的内核中,一些浮点值以奇怪的方式被舍入。我不认为~0.13算作~34的小不精确。这个答案完全是一个借口。@muistooshort可以提供您自己对底层C模块的分析,或者您认为问题可能出在受影响的口译员身上的任何地方。我已经为OP的问题提供了一个务实的解决方案,而且这个解决方案显然是有效的。关于语言实现者为什么以他们的方式实现事情的问题是离题的,应该以基于观点的方式结束。然而,你当然有权放弃你的自行车,但既然MRI bug跟踪器不是这样,我认为一个具体的答案显示如何可靠地初始化BigDecimal是一个有效的答案。YMMV@CodeGnome,语言设计决策和实现中的bug源之间存在差异(假设这是一个)。一个切实可行的解决方案总是受欢迎的,如果你不想自己跟踪这个问题,那也没关系,但不要因此而把它当作离题。某事物的低级实现中的一个非常狭隘、特定的bug与“基于主要观点”的bug截然相反。MRI缺陷追踪者评论是非顺序的。在关于开源工具的SO中,超过50%的问题可以通过查看文档或在github上打开一个问题来回答。@CodeGnome,据我所知,SO的任务正是成为google上第一个搜索任何足够具体的编程问题的结果。这是其中之一。我在这页上找不到我想要的答案。