【问题标题】:Unsigned to signed without comparison无符号到无比较的有符号
【发布时间】:2013-06-17 16:24:00
【问题描述】:

要将 32 位无符号整数转换为有符号整数,可以使用:

function convert(n)
    if n >= 2 ^ 31 then
        return n - 2 ^ 32
    end
    return n
end

没有这种比较可以做到吗?

PS:这是 Lua,因此我不能像在 C 中那样“转换”。

【问题讨论】:

  • 最好的微优化。

标签: optimization casting lua bit-manipulation unsigned-integer


【解决方案1】:

也许你可以通过位操作来做到这一点。在 Smalltalk 中,这将是:

^self - (2*(self bitAnd: 16r80000000))

显然 bitops 在 Lua 中不是原生的,但似乎有各种位库可用,请参阅 http://lua-users.org/wiki/BitwiseOperators

一旦你找到合适的 bitand 函数,就会是这样的

return n - bitand(n,MAXINT)*2

【讨论】:

  • 谢谢!在 LuaJIT 下,这比上面的快 3 倍!
【解决方案2】:

不是在普通的 Lua 中。您当然可以通过编写来优化求幂和 if 语句:

local MAXINT, SUBT = math.pow(2, 31), math.pow(2, 32)
function convert(n)
    -- Like C's ternary operator
    return (n >= MAXINT and n - SUBT) or n
end

我不知道优化 if 语句是否会对解释器有很大帮助;我认为不适合 LuaJIT;但可能是普通的 Lua?

如果您真的想避免比较,请选择 C,例如(未经测试的代码!):

int convert(lua_State *L)
{
    lua_pushinteger(L, (int) ((unsigned int) luaL_checklong(L, 1)));
    return 1;
}

但是,堆栈开销可能会破坏目的。

微优化有什么具体原因吗?

编辑:我一直在考虑这个,在普通 Lua 中实际上是可能的:

local DIV, SUBT = math.pow(2, 31) + 1, math.pow(2, 32)
-- n MUST be an integer!
function convert(n)
    -- the math.floor() evaluates to 0 for integers 0 through 2^31;
    -- else it is 1 and SUBT is subtracted.
    return n - (math.floor(n / DIV) * SUBT)
end

我不确定它是否会提高性能;除法必须比条件跳转快。 然而,从技术上讲,这回答了问题并避免了比较。

【讨论】:

  • 谢谢!是的,有一个原因 - 我分析了一些代码,我需要将许多无符号整数转换为有符号整数。而那个愚蠢的比较让它慢了一半。我尝试了你的第一个解决方案(错误修复:return (n >= MAXINT and n - (2*MAXINT)) or n),它的速度与if的速度差不多
  • 在答案中的代码中添加了错误修复。你试过 C 版本吗?
  • 不,我想使用普通的 Lua。
  • 添加解决方案;此外,将“lua”标签添加到这个问题将有助于找到它。
  • 很抱歉取消选中标记,但@aka.nice 提供了一个非常好的答案,希望你也觉得它很有趣。
猜你喜欢
  • 2011-07-21
  • 2016-08-07
  • 1970-01-01
  • 1970-01-01
  • 2014-01-28
  • 1970-01-01
  • 1970-01-01
  • 2021-10-31
相关资源
最近更新 更多