为什么 "The [integer<->float] conversion strategy is changed depending on the size of the float" 在 Erlang 中,我该如何观察?

Why is "The [integer<->float] conversion strategy is changed depending on the size of the float" in Erlang and how can I observe this?

Erlang docs 说:

"当比较一个整数和一个浮点数时,精度较低的项被转换为另一个项的类型,除非运算符是 =:= 或 =/= 之一。浮点数比浮点数更精确一个整数,直到浮点数的所有有效数字都在小数点左侧。当浮点数为 larger/smaller 比 +/-9007199254740992.0 时会发生这种情况。转换策略根据浮点数的大小而改变,否则比较大浮点数和整数将失去传递性。"

如何观察大型浮点数的转换策略变化?

我读到文档说 (...digits).0 == (...digits) 对于 (...digits) 的小序列是错误的,但对于更大的序列(...数字)是正确的,但这似乎不是他们给出的价值案例:

> 9007199254740992.0 == 9007199254740992
true
> 9.0 == 9.
true

但是,对于更大的数字似乎确实如此。关于转换策略更改的特定边界,文档是否已过时?

> 999999999999999999999.0 ==  999999999999999999999.
false
> 9.0 == 9.

正确

为什么?

更改较大数字的浮点数<->整数比较策略的原因是“否则大浮点数和整数的比较将失去其传递性”。我不明白 - 是否有此算法如何避免传递失败的示例?

鉴于浮点数和整数具有不同的精度(浮点数在值接近 0 时分辨率较高,在值远离 0 时分辨率较低),如果要比较它们,则需要将其中一个转换为另一个.

如果此转换是从精度较高的转换到精度较低的转换,则这是可能的:

H2 = H1 + Delta,
true = L == H1,
true = L == H2,
true = H1 /= H2. %% In this case, both H1 and H2 are equal to L but different between themselves

出于这个原因(传递性),转换以相反的方式执行,从低精度到高精度。

让我们考虑这三个数字:

A = 9007199254740992.
B = 9007199254740993.
C = 9007199254740992.0.

根据实际规则,AC等同于B

> A == B.  %% A and B are both integers, compared as integers
false
> A == C.  %% C gets converted to an integer before comparison
true
> B == C.  %% C gets converted to an integer before comparison
false

如果反过来,高于阈值的整数在与浮点数比较之前被转换为浮点数怎么办?

> A == B.         %% no change, because they are both integers
false
> float(A) == C.  %% no surprise here
true
> float(B) == C.  %% B cannot be accurately represented as a floating point value!
true

所以现在看起来AB都等于C,但彼此不相等,相等比较失去了传递性。

9007199254740992等于253,53也是64位IEEE 754浮点数中的有效位数*,因此对于大于此的数字,浮点类型无法表示每个整数。例如,9007199254740992.0 + 1 == 9007199254740992.0 returns true。这就是为什么 Erlang 整数类型(它是一个 bignum,因此可以表示任意大的整数)在这个阈值之上被认为更精确。

* 二进制表示仅使用 52 位作为有效数,并且由于第一位几乎始终为 1 而得以解决。搜索“次正规数”以了解更多信息。