Page 2 of 2

Re: convert a number to binary with lua ?

Posted: Sat Mar 10, 2018 11:52 am
by zorg
okay, that's a simple thing then; rgba values are usually unsigned.

Code: Select all

-- Converts a byte to a string of 0s and 1s.
function byte2bin(n)
local t = {}
  for i=7,0,-1 do
    t[#t+1] = math.floor(n / 2^i)
    n = n % 2^i
  end
  return table.concat(t)
end
This can be extended to larger numbers too, automatically: (hopefully i didn't fudge up the decimal digit calculation...)

Code: Select all

-- Converts a byte to a string of 0s and 1s.
function byte2bin(n)
local t, d = {}, 0
  d = math.log(n)/math.log(2) -- binary logarithm
  for i=math.floor(d+1),0,-1 do
    t[#t+1] = math.floor(n / 2^i)
    n = n % 2^i
  end
  return table.concat(t)
end
-- And negatives:

Code: Select all

-- Converts a byte to a string of 0s and 1s.
function byte2bin(n)
  local t, d = {}, 0
  d = math.log(n)/math.log(2) -- binary logarithm
  if n<0 then
    -- two's complement
    d = d + 1
    n = 2^d - math.abs(n)
  end
  for i=math.floor(d+1),0,-1 do
    n = n % 2^i
  end
  return table.concat(t)
end
fractions are trickier; fixed-point notation would be doable, but computers nowadays usually use the IEEE floating point representations, and those are hard to code by hand like this.

Re: convert a number to binary with lua ?

Posted: Sat Mar 10, 2018 12:59 pm
by Tuxion
Thank you very much, that's exactly what I wanted to know.

Should I use the same method if I want to convert to hexadecimal?

Re: convert a number to binary with lua ?

Posted: Sat Mar 10, 2018 1:10 pm
by zorg
You could change a few things to have that, mostly the number 2s in a few lines... but on the other hand:

Code: Select all

n = 154
print(('%X'):format(n))
the format string also works with %x (lowercase x) if you prefer the hex digits lowercase.

Re: convert a number to binary with lua ?

Posted: Sat Mar 10, 2018 3:10 pm
by pgimeno
Float isn't very difficult. math.frexp does the heavy lifting.

Code: Select all

local function int2bin(n)
  local result = ''
  while n ~= 0 do
    if n % 2 == 0 then
      result = '0' .. result
    else
      result = '1' .. result
    end
    n = math.floor(n / 2)
  end
  return result
end

local function float2bin(n)
  if math.abs(n) == math.huge then
    -- plus or minus infinity
    return n > 0 and 'inf' or '-inf'
  end
  if not n == n then
    -- nan
    return 'nan'
  end

  local m, e = math.frexp(n)
  local result = int2bin(math.abs(m * 2^53))

  local len = #result
  if e > 53 then
    -- big number, add zeros on the right
    result = result .. ('0'):rep(e - 53)
  elseif e < 1 then
    -- small number, add zeros on the left
    result = ('0'):rep(1 - e) .. result
    e = 1
  end

  -- Add the point
  result = result:sub(1, e) .. '.' .. result:sub(e + 1)

  -- remove zeros on the right including point
  result = result:gsub('%.?0*$', '')

  if n < 0 then
    return '-' .. result
  end
  return result
end

repeat
  io.write('> ')
  local s = io.read('*line')
  if s == nil or s == '' then io.write('\n') break end
  print(float2bin(loadstring('return (' .. s .. ')')()))
until false

Re: convert a number to binary with lua ?

Posted: Sat Mar 10, 2018 4:40 pm
by zorg
Yes but that's sure as hell not the binary representation of an IEEE single or double precision float :P
Also, concatenation is still slower than tables, that said, your code for int2bin is simpler than mine, since it avoids logarithms and stuff... though not sure if it could handle signed ints without it.

Code: Select all

local function int2bin(n)
  local result = {}
  while n ~= 0 do
    if n % 2 == 0 then
      result[#result+1] = '0'
    else
      result[#result+1] = '1'
    end
    n = math.floor(n / 2)
  end
  return table.concat(result)
end

Re: convert a number to binary with lua ?

Posted: Sat Mar 10, 2018 5:07 pm
by pgimeno
Yeah, I optimized for clarity, not speed :)

Edit: And, well, it's the binary representation of the number that the float represents, which I thought was what was asked.

Re: convert a number to binary with lua ?

Posted: Sat Mar 10, 2018 5:49 pm
by ivan
Tuxion, the standard way is to format the number as a hex:

Code: Select all

hex = string.format("%x", number)
print(hex)
"%06x" RGB, 6 digits
"%08x" RGBA, 8 digits
Printing as binary is possible but it's just not very practical/common.

PS. But if you insist on printing binary:

Code: Select all

local h2b = {
['0']='0000', ['1']='0001', ['2']='0010', ['3']='0011',
['4']='0100', ['5']='0101', ['6']='0110', ['7']='0111',
['8']='1000', ['9']='1001', ['A']='1010', ['B']='1011',
['C']='1100', ['D']='1101', ['E']='1110', ['F']='1111'
}
function hex2bin(n)
  return n:upper():gsub(".", h2b)
end
function dec2bin(n)
  return hex2bin(tostring(n):format("%X"))
end
Nice and simple, no math involved!