72

在 ruby​​ 中,为什么我可以为 0.0 浮点数分配一个负号,这个功能是否有用?有人可以向我解释一下吗?

-0.0
#=> -0.0

-0.0 * -1
#=> 0.0
4

4 回答 4

105

您可以在 Ruby 中为 0.0 浮点数分配负号,因为所有IEEE 754浮点数都有一个符号位来指示该数字是正数还是负数。

以下是 和 的二进制2.5表示-2.5

[2.5].pack('f').unpack1('b*')
#=> "00000000000000000000010000000010"

[-2.5].pack('f').unpack1('b*')
#=> "00000000000000000000010000000011"

最后一位是符号位。请注意,所有其他位都是相同的。

另一方面,符号位为零0

['00000000000000000000000000000000'].pack('b*').unpack1('f')
#=> 0.0

和零,符号位为1

['00000000000000000000000000000001'].pack('b*').unpack1('f')
#=> -0.0

尽管0.0-0.0在数值上相等,但它们在对象级别上并不相同:

(0.0).eql?(-0.0)   #=> true
(0.0).equal?(-0.0) #=> false

负零有一些特殊的性质。例如:

1 / 0.0    #=> Infinity
1 / -0.0   #=> -Infinity

显式分配-不是获得-0.0. -0.0作为基本算术运算的结果,您还可能得到:

-1.0 * 0 #=> -0.0
于 2019-11-04T10:48:40.890 回答
41

数学运算具有实数结果,但我们将这些实数结果映射到最接近的浮点数上,这称为“舍入”。对于每个浮点数,都有一个实数范围会四舍五入到该浮点数,有时将浮点数视为与该实数范围相同是有用的。

由于浮点数的供应是有限的,因此必须有一个最小的正浮点数,而它的相反,最小(幅度)负浮点数。但是比那些更小的实数结果会怎样呢?好吧,他们必须“四舍五入”。但是“一个非常小的大于零的数”和“一个非常小的小于零的数”是完全不同的东西,具有非常不同的数学行为,那么我们为什么要因为我们四舍五入就失去它们之间的区别呢?我们不必。

因此,浮点 0 不仅包括实数 0,它还包括太小而无法表示的数。并且浮点数 -0 包括太小而无法表示负数。当您在算术中使用它们时,它们遵循“负乘正等于负;负乘负等于正”之类的规则。尽管我们在舍入过程中几乎忘记了这些数字的所有内容,但我们仍然没有忘记它们的符号。

于 2019-11-04T19:53:51.200 回答
26

它不是 Ruby 的特性,而是浮点数规范的一部分。看到这个答案。负零等于正零:

-0.0 == 0.0
# => true
于 2019-11-04T10:31:08.483 回答
2

您可能需要 -0.0 的一个示例是使用具有垂直极点的函数(例如,正切、割线或余割线)需要朝正确的方向移动。您可能最终会除以得到负无穷大,并且您不想将其绘制成一条向上射向正无穷大的垂直线。或者您可能需要从下方渐近接近 0 的函数的正确符号,例如,如果您有负数的指数衰减并检查它是否仍然为负。

于 2019-11-05T19:04:34.797 回答