1

Чтобы преобразовать 32-разрядное беззнаковое в знаковое целое число можно было бы использовать:Unsigned подписанному без сравнения

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

Можно ли это сделать без этого сравнения?

PS: Это Lua, поэтому я не могу "отбрасывать" как в C.

+0

Микро-оптимизация в лучшем виде. –

ответ

5

Возможно, вы могли бы сделать это с помощью битовых операций. В Smalltalk, который был бы:

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

Видимо bitops не являются родными в Lua, но различная битная библиотека кажется доступной, см http://lua-users.org/wiki/BitwiseOperators

После того, как вы найдете соответствующую функцию bitand, что будет что-то вроде

return n - bitand(n,MAXINT)*2 
+0

Спасибо! В LuaJIT это в 3 раза быстрее, чем выше! –

0

Не в простом Lua. Конечно, вы можете оптимизировать экспоненциация и если-заявление прочь письма:

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 

Я не знаю, если оптимизировать заявление, если одноразовым будет много помощи переводчику; не для LuaJIT, я думаю; но, вероятно, для простого Луа?

Если вы действительно хотите избежать сравнения, перейдите на C, например. (непроверенный код!):

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

Однако накладные расходы на стеке, вероятно, победят цель.

Любые конкретные причины для микро-оптимизации?

Edit: Я думал об этом, и это на самом деле возможно в простом 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 

Я не уверен, будет ли это повысить производительность; разделение должно быть быстрее, чем условный скачок. Технически, однако, это отвечает на вопрос и позволяет избежать сравнения.

+0

Спасибо! Да, есть причина - я профилировал часть кода, и мне нужно преобразовать множество целых чисел без знака в подписанные. И это глупое сравнение делает его наполовину медленным. Я попробовал ваше первое решение (исправлено ошибка: «return (n> = MAXINT и n - (2 * MAXINT)) или n'), и это примерно такая же скорость, что и с' if' –

+0

. Добавлен исправление к коду в ответ. Вы попробовали версию C? – jpflorijn

+0

Нет, я бы хотел использовать простой Lua. –