在Flanagan和Matz的 Ruby编程语言中,我读到了这个:
Numeric
类在==
运算符中执行简单的类型转换,因此(例如)Fixnum 1
和Float 1.0
比较相等。
鉴于即使两个Float
代表1.0
由于四舍五入也会导致等式测试失败,如何保证 Fixnum
和{{{}之间的相等性1}?无法保证在 Float
和Decimal
之间?
或者这本书是不精确的,因为这不是本章背景下的焦点?
编辑,希望增加清晰度:
我刚刚读到IEEE754(浮点)可以精确地表示高达2 24 的整数,并且加倍到2 53 。根据{{3}},2 53 +1(9,007,199,254,740,993)是第一个不能用double精确表示的整数(因此浮点数)。那我的问题是,怎么做
Float
评估为9007199254740993.0 == 9007199254740993
?不应该舍入导致左侧(true
或double
无法表示)舍入到与右侧不匹配的值(精确整数) )?
答案 0 :(得分:3)
正如负责该比较的函数source code(rb_integer_float_eq
)所描述的那样,它们都被提升为双倍然后进行比较,因此它最终将成为1.0 == 1.0
答案 1 :(得分:2)
您确定不保证0.9 == 0.9
这样的表达式吗?我不这么认为。它在我的机器上成功,即使存在舍入错误,算法也应始终将相同的文字表达式映射到具有相同舍入误差的相同浮点数。例如,如果表达式"0.9"
在内部表示为0.900001
,则它始终如此。它有时不会映射到0.900000
,有时会映射到0.900002
。所以应该保证平等。
关于Fixnum
和Float
之间的比较,如果将fixnum文字转换为浮点数,它也会映射到同一个浮点数,就像它从一开始就是一个浮点数一样,具有相同的浮点数舍入误差。换句话说,以下两个进程以相同的float结束:
"1.0"
→一些带有舍入错误的内部浮点数(例如0.999999
)"1"
→内部装订1
→某些带有舍入错误的内部浮动(0.999999
) 编辑或者,正如fmendez所说,如果整数内部精确映射到一个浮点数,那么浮点数就完全对应一个整数(如"1.0"
,"2.0"
等。)内部浮点表达式中没有任何舍入错误。所以无论如何都会保证平等。
答案 2 :(得分:0)
在Squeak / Pharo Smalltalk中,我改变了相等/不等式比较测试,始终将不精确的算术值(浮点)提升为精确的算术值(Integer Fraction ScaledDecimal)。 见http://bugs.squeak.org/view.php?id=3374
在此之前很久就用各种口味的食物来做 见http://www.lispworks.com/documentation/lcl50/aug/aug-170.html
如果你不这样做,你会降低相等性测试的一些属性,因为2 ^ 54 + 1和2 ^ 54-1可能都等于相同的float double(2 ^ 54)。与不平等相同。您还可以使用字典(散列映射)和数字集来解决各种麻烦。