为什么可以假设INT_MIN在浮点数中有精确的表示? - lua_numbertointeger

4
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位整数和64位浮点数同样适用... 对于64位整数和32位浮点数呢?)

2个回答

4
在二进制补码表示法中,通常最小值只有1位被设置,即C语言的INT_MIN可能为0x80000000。因此,它可以在float中精确表示,因为它只有一个有效位,并且可以被规范化而不会失去精度。
但是INT_MAX,例如0x7FFFFFFF,有31个有效位,比float的有效数字更多,因此不能用float来精确表示。

3

INT_MIN以2的补码形式表示,是2的幂次方(取反),因此具有精确的浮点数表示。 (潜在范围异常128位int和32位float

因此,(n) >= (LUA_NUMBER)(LUA_MININTEGER) 中的计算是没有转换/四舍五入误差的。


然而,对于64位浮点数和32位intif()测试存在一个功能性问题。

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_MININTEGER - 1 ... LUA_MININTEGER)范围内的值进行转换。这样的浮点数值仅存在于罕见的非标准Lua配置“int32 + float64”中。您可以自己构建此类Lua,但标准Lua具有“int64 + float64”。 - Egor Skriptunoff
我认为,在64位浮点数和32位整数中,lua_numbertointeger不会被使用(至少在Lua虚拟机的比较操作中),因为它可以将整数转换为浮点数而不会失去精度(并以此方式进行比较)。但是了解这一点仍然很好,谢谢。 - user673679

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接