位运算工具

lua-users home
wiki

这些是完全用 Lua 实现的位运算。

异或

-- Bitwise XOR - thanks to Reuben Thomas
local floor = math.floor
function bxor (a,b)
  local r = 0
  for i = 0, 31 do
    local x = a / 2 + b / 2
    if x ~= floor (x) then
      r = r + 2^i
    end
    a = floor (a / 2)
    b = floor (b / 2)
  end
  return r
end

如果您需要速度,以下方法要快得多(Arno Wagner <[email protected]>)

function bin_xor(x, y)
   local z = 0
   for i = 0, 31 do
      if (x % 2 == 0) then                      -- x had a '0' in bit i
         if ( y % 2 == 1) then                  -- y had a '1' in bit i
            y = y - 1 
            z = z + 2 ^ i                       -- set bit i of z to '1' 
         end
      else                                      -- x had a '1' in bit i
         x = x - 1
         if (y % 2 == 0) then                  -- y had a '0' in bit i
            z = z + 2 ^ i                       -- set bit i of z to '1' 
         else
            y = y - 1 
         end
      end
      y = y / 2
      x = x / 2
   end
   return z
end

也可以不使用幂函数来实现。以下实现方式在大多数情况下应该比上面更快。虽然我还没有通过实验验证这一点。

function xor(a,b)
   pow = 1
   c = 0
   while a > 0 or b > 0 do
      c = c + (XOR_l[(a % 2)+1][(b % 2)+1] * pow)
      a = math.floor(a/2)
      b = math.floor(b/2)
      pow = pow * 2
   end
   return c
end

XOR_l =
{ 
   {0,1},
   {1,0},
}

如果速度不是您的主要考虑因素,以下方法可能更短。

local function nand(x,y,z)
    z=z or 2^16
    if z<2 then
        return 1-x*y
    else
        return nand((x-x%z)/z,(y-y%z)/z,math.sqrt(z))*z+nand(x%z,y%z,math.sqrt(z))
    end
end
math["not"]=function(y,z)
    return nand(nand(0,0,z),y,z)
end
math["and"]=function(x,y,z)
    return nand(math["not"](0,z),nand(x,y,z),z)
end
math["or"]=function(x,y,z)
    return nand(math["not"](x,z),math["not"](y,z),z)
end
math["xor"]=function(x,y,z)
    return math["and"](nand(x,y,z),math["or"](x,y,z),z)
end

标志

function testflag(set, flag)
  return set % (2*flag) >= flag
end

function setflag(set, flag)
  if set % (2*flag) >= flag then
    return set
  end
  return set + flag
end

function clrflag(set, flag) -- clear flag
  if set % (2*flag) >= flag then
    return set - flag
  end
  return set
end


-- Test suite
b = {
  ['_0000'] = 0, ['_0001'] = 1, ['_0010'] = 2, ['_0011'] = 3,
  ['_1000'] = 8, ['_1010'] = 10, ['_1011'] = 11,
}
assert(not testflag(b._0000, b._0001))
assert(not testflag(b._0000, b._0010))
assert(not testflag(b._0010, b._0001))
assert(    testflag(b._0010, b._0010))
assert(setflag(b._0000, b._0001) == b._0001)
assert(setflag(b._0000, b._0010) == b._0010)
assert(setflag(b._1010, b._0001) == b._1011)
assert(setflag(b._1010, b._0010) == b._1010)
assert(clrflag(b._0000, b._0001) == b._0000)
assert(clrflag(b._0000, b._0010) == b._0000)
assert(clrflag(b._1010, b._0001) == b._1010)
assert(clrflag(b._1010, b._0010) == b._1000)

另请参阅


最近更改 · 偏好设置
编辑 · 历史记录
最后编辑于 2013 年 9 月 25 日上午 6:30 GMT (差异)