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位float
,LUA_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)
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位float
,LUA_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)