为啥以下在红宝石中有效?

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 == 9false?浮点恶作剧... 又一个“为什么数字在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

等等。

【讨论】:

只是补充一点——假设你使用的是 ruby​​ v2.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?

字节顺序测试:为啥以下代码有效?

为啥以下代码在在线 ide(gcc 7.2.0) 上有效,但在 ubuntu 上出错?

为啥 08 在 Java 中不是有效的整数文字?

为啥在这种情况下只有回溯有效?

为啥 WHERE 在 Web UI 中有效,但在 gsutil 中无效?