lua_numbertointeger - 为什么我们可以假设 INT_MIN 具有精确的浮点数表示形式?

lua_numbertointeger - why can we assume INT_MIN has an exact representation as a float?

Lua 在内部将数字存储为整数或浮点数。当对两种不同类型的数字进行比较运算(如小于)时,需要从一种类型转换为另一种类型进行比较。

整数和浮点数类型因配置/平台而异,但做出了某些假设。 (我只对“普通”32 或 64 位二进制补码整数和 32 或 64 位 IEEE754 浮点数真正感兴趣)。

当整数类型在浮点格式中可能没有精确表示时,Lua 尝试将浮点值转换为整数。

这是在宏中完成的 lua_numbertointeger:

/*
@@ lua_numbertointeger converts a float number with an integral value
** to an integer, or returns 0 if float is not within the range of
** a lua_Integer.  (The range comparisons are tricky because of
** rounding. The tests here assume a two-complement representation,
** where MININTEGER always has an exact representation as a float;
** MAXINTEGER may not have one, and therefore its conversion to float
** may have an ill-defined value.)
*/
#define lua_numbertointeger(n,p) \
  ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \
   (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \
      (*(p) = (LUA_INTEGER)(n), 1))

我的问题是:

假设LUA_NUMBER是32位floatLUA_INTEGER是32位int 为什么我们可以假设 LUA_MIN_INTEGER(即 INT_MIN)在浮点类型中具有精确表示。

(对于 64 位 int 和 64 位浮点数也是一样的...它可以与 64 位 int 和 32 位浮点数一起使用吗?)

在 2 的补码表示中,最小值通常只有 1 位设置,如在 C 的 INT_MIN 中可能是 0x80000000。所以它可以用 float 精确表示,因为它只有一个有效位,并且可以在不损失精度的情况下进行归一化。

但是INT_MAX也就是0x7FFFFFFF有31个有效位,比float的有效位多,所以不能用float精确表示.

INT_MIN 作为 2 的补码,是 2 的幂(取反),因此具有精确的 FP 表示。 (潜在范围异常 128 位 int 和 32 位 float

因此 (n) >= (LUA_NUMBER)(LUA_MININTEGER) 中的数学是准确的,没有 conversion/rounding 错误。


然而,在 if() 测试中,64 位浮点和 32 位 int 存在功能问题。

lua_numbertointeger(n,p) 在极端情况下是错误的。由于 (LUA_INTEGER)(n) 截断了 n 的小数部分,我希望正确的前面 if 测试是 (n) - (LUA_NUMBER)(LUA_MININTEGER) > -1 ... 而不是 (n) >= (LUA_NUMBER)(LUA_MININTEGER)。这允许 (LUA_MININTEGER - 1 ... LUA_MININTEGER) 中的值进行转换。

转换值范围应为

(INT_MIN - 1 .... INT_MAX + 1)
// not 
[INT_MIN     .... INT_MAX + 1)