为啥以下在红宝石中有效?
Posted
技术标签:
【中文标题】为啥以下在红宝石中有效?【英文标题】:Why the following works in ruby?为什么以下在红宝石中有效? 【发布时间】:2016-09-13 16:43:48 【问题描述】:to_a
在这种情况下,在整数范围内的行为会有所不同。
最多 15 位小数,include?
返回 false
,但一旦达到 16 位小数,数组就会将小数位视为数组的一部分。
为什么?
2.2.1 :020 > (1..9).to_a.include?(8.999999999999999)
=> false
2.2.1 :021 > (1..9).to_a.include?(8.9999999999999999)
=> true
2.2.1 :022 >
以及为什么仅限范围说这是真的
2.2.1 :001 > (1..9).include?(8.9)
=> true
【问题讨论】:
(1..9).include?(8.9)
与 1 <= 8.9 && 8.9 <= 9
相同。我认为返回true
的原因很明显。但是(1..9).to_a
返回数组[1,2,3,4,5,6,7,8,9]
。这就引出了一个问题,为什么8.9999999999999999 == 9
eval 为true
,但8.999999999999999 == 9
为false
?浮点恶作剧...
又一个“为什么数字在x语言中不起作用”问题。 xd
@spickermann,你应该把它写成答案。
【参考方案1】:
(1..9).include?(8.9)
与 1 <= 8.9 && 8.9 <= 9
相同。我认为这很明显为什么返回true
。
但是(1..9).to_a
返回数组[1,2,3,4,5,6,7,8,9]
。这导致另一个观察结果:
8.999999999999999 == 9 #=> false
8.9999999999999999 == 9 #=> true
Floating point shenanigans.
您可能想使用next_float
来研究下一个可表示的浮点数(正如 Tom Lord 在 cmets 中指出的那样):
8.999999999999999.next_float #=> 9.0
8.9999999999999999.next_float #=> 9.000000000000002
等等。
【讨论】:
只是补充一点——假设你使用的是 rubyv2.2+
,你可以使用 Float#next_float
来帮助理解发生了什么:(8.999999999999999).next_float == 9.0; (8.9999999999999999).next_float == 9.000000000000002
- 换句话说,8.9999999999999999
是完全一样的在红宝石中作为9.0
的东西。这种浮点舍入错误并非特定于 ruby。
是的,当您在 irb 上运行 8.9999999999999999 时,它与 9 相同,但当您运行 8.999999999999999 时,它返回 8.999999999999998
绝对是浮点恶作剧,但请记住 Range 不是数组,因此要问为什么 8.99 包含在 1..9
而不是 (1..9).to_a
是不可能的。从概念上讲,(1..9).to_a
与 (1..9).step(1).to_a
相同。把它变小:(8.1)..(9.0).to_a
将失败,TypeError
,但(8.1)..(9.0).step(0.1).to_a
不会。以上是关于为啥以下在红宝石中有效?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 MySQL 中每个有效的 SELECT 都不是有效的 VIEW?