我在其他语言中使用过这个,但是 lua 似乎缺少这个相当有用的功能。
你们中的一个好家伙可以给我一个lua函数来获取传递给它的数字的符号吗?
function math.sign(x)
if x<0 then
return -1
elseif x>0 then
return 1
else
return 0
end
end
以防万一有人偶然发现这个:,这是我的较短版本:
function sign(x)
return x>0 and 1 or x<0 and -1 or 0
end
我认为这个想法是返回 1 或 -1 来表示正面或负面。我认为您不希望它返回 0。可能会产生灾难性的影响。想象一下,当一个值返回 0 时,试图通过将它乘以 sign(x) 来改变它的符号。而不是改变符号,你会将值更改为 0。
我会坚持
function sign(x)
return (x<0 and -1) or 1
end
使用 LuaJIT,如果 sign 函数被 JIT 编译,这实际上更快:
function sign(x)
return math.max(math.min(x * 1e200 * 1e200, 1), -1)
end
原因是它避免了分支,这可能很昂贵。双倍乘法确保即使输入在非正规范围内,结果也是正确的。Infinity 不能使用,因为输入为零,它会产生 NaN。
仅在 x86 中测试。我不能保证它是 LuaJIT 支持的其他处理器中最快的。
我建造了这个是因为我需要精确处理-0
以及所有其他版本都无法处理的问题。+0
nan
这个想法是直接解释符号位并为此测试提供无分支版本。在纯 Lua 中,您必须使用 tostring(x) 检查 +-0。
local _sign_helper = ffi.new("union { double d; uint64_t ul; int64_t l; }[1]")
local function sign(num)
-- to get access to the bit representation of double
_sign_helper[0].d = num
-- reinterpret it as ulong to access the sign bit
-- 1. move the bit down to the first bit
-- 2. multiply by -2 to move the range from 0/1 to 0/-2
-- 4. add 1 to reduce the range to -1/1
-- one test version for NaN handling (might be faster, did not test.)
-- return num ~= num and num or (tonumber(bit.rshift(_sign_helper[0].ul, 63)) * -2 + 1)
-- branchless version: num - num will always be 0 except for nan.
return (tonumber(bit.rshift(_sign_helper[0].ul, 63)) * -2 + 1) * ((num - num + 1) / 1)
end
print("(number < 0)", sign(-3)) -- > -1
print("(number > 0)", sign(3)) -- > 1
print("(nan)", sign(0 / 0)) -- > nan
print("(-inf)", sign(-0 / 1)) -- > -1
print("(+inf)", sign(0 / 1)) -- > 1
print("(+0)", sign(0)) -- > 1
print("(-0)", sign(-0)) -- > -1
您还可以像这样获得数字的符号:
x/ math.abs(x)
我只会将那个用于整数,并且由于 Lua 不区分整数和浮点数,所以我根本不会在 Lua 中使用它。
一种变化可能是
function sign(x)
if x<0 then
return "-"
elseif x>0 then
return "+"
else
return ""
end
end
在数学上,符号是“+”或“-”(符号),而不是数字(如 +1 或 -1)
你可以检查sign
这样的:
i = -2
if i == math.abs(i) then -- or i >= 0
print "positive"
else
print "negative"
end