How to format numbers in Lua?

Asked

Viewed 1,079 times

5

I would like to know how to format the variable:

local n = 100000000

So you can come back like this:

100.000.000

Separated by dots, someone knows how to do?

3 answers

4

The form proposed by page Formatting Numbers - lua-users.org is to use the function string.gsub as follows:

function formatarNumero(valor)
  local formatado = valor
  while true do  
                                          -- O "." entre "%1" e "%2" é o separador
    formatado, n = string.gsub(formatado, "^(-?%d+)(%d%d%d)", '%1.%2') 
    if ( n ==0 ) then
      break
    end
  end
  return formatado
end

The expression (^-?\d+)(\d\d\d) basically will break the value into pieces thanks to the quantifier ? that will repeat zero or one time, as many times as it is possible to satisfy it.

An alternative way using the function string.match:

function formatarNumero(valor) -- Créditos http://richard.warburton.it
    local esquerda, num, direita = string.match(valor,'^([^%d]*%d)(%d*)(.-)$')
    return esquerda..(num:reverse():gsub('(%d%d%d)', '%1.'):reverse())..direita
end

Example of use:

print(formatarNumero(1))          -- 1
print(formatarNumero(10))         -- 10
print(formatarNumero(100))        -- 100
print(formatarNumero(1000))       -- 1.000
print(formatarNumero(10000))      -- 10.000
print(formatarNumero(100000))     -- 100.000
print(formatarNumero(1000000))    -- 1.000.000
print(formatarNumero(10000000))   -- 10.000.000
print(formatarNumero(100000000))  -- 100.000.000
print(formatarNumero(1000000000)) -- 1.000.000.000
print(formatarNumero(-123))       -- -123

See demonstração

Updating

The above functions fail when formatting very large numbers like 10000000000, to solve this problem, it will be necessary to use the library lbc created by lhf, which is based on the WILDEBEEST bc for arbitrary precision numerical processing.

Follow the code below:

require "bc"

function formatarNumero(valor)
  numero = bc.number(valor)
  local formatado = tostring(numero)
  while true do
    formatado, n = string.gsub(formatado, "^(-?%d+)(%d%d%d)", '%1.%2')
    if ( n ==0 ) then
      break
    end
  end
  return formatado
end

Example of use:

print(formatarNumero(1))            -- 1
print(formatarNumero(10))           -- 10
print(formatarNumero(100))          -- 100
print(formatarNumero(1000))         -- 1.000
print(formatarNumero(10000))        -- 10.000
print(formatarNumero(100000))       -- 100.000
print(formatarNumero(1000000))      -- 1.000.000
print(formatarNumero(10000000))        -- 10.000.000
print(formatarNumero(100000000))       -- 100.000.000
print(formatarNumero(1000000000))      -- 1.000.000.000
print(formatarNumero(10000000000))     -- 10.000.000.000
print(formatarNumero(100000000000))    -- 100.000.000.000
print(formatarNumero(1000000000000))   -- 1.000.000.000.000
print(formatarNumero(10000000000000))  -- 10.000.000.000.000
print(formatarNumero(100000000000000))     -- 100.000.000.000.000
print(formatarNumero(1000000000000000))    -- 1.000.000.000.000.000
print(formatarNumero(10000000000000000))   -- 10.000.000.000.000.000

print(formatarNumero(-1))            -- -1
print(formatarNumero(-10))           -- -10
print(formatarNumero(-100))          -- -100
print(formatarNumero(-1000))         -- -1.000
print(formatarNumero(-10000))        -- -10.000
print(formatarNumero(-100000))       -- -100.000
print(formatarNumero(-1000000))      -- -1.000.000
print(formatarNumero(-10000000))        -- -10.000.000
print(formatarNumero(-100000000))       -- -100.000.000
print(formatarNumero(-1000000000))      -- -1.000.000.000
print(formatarNumero(-10000000000))     -- -10.000.000.000
print(formatarNumero(-100000000000))    -- -100.000.000.000
print(formatarNumero(-1000000000000))   -- -1.000.000.000.000
print(formatarNumero(-10000000000000))  -- -10.000.000.000.000
print(formatarNumero(-100000000000000))     -- -100.000.000.000.000
print(formatarNumero(-1000000000000000))    -- -1.000.000.000.000.000
print(formatarNumero(-10000000000000000))   -- -10.000.000.000.000.000

3


function dot_string(s)
    -- não precisamos de pontinhos para números até 999
    if s:len() <= 3 then
        return s
    end 

    -- senão, colocamos o pontinho no último grupo de 3 e repetimos o processo para o que sobrou
    return dot_string(s:sub(1, -4)) .. "." .. s:sub(-3)
end 

function dot_number(n)
    -- TODO: n < 0
    -- TODO: n != int(n)
    -- TODO: n grande
    return dot_string(tostring(n))
end

If n is negative, fractional or giant, tostring() will do lambança, but otherwise the function meets what you asked for (at least the first two cases are easy to treat with ifs in the dot_number before calling the dot_string).

Example:

print(dot_number(0))
print(dot_number(10))
print(dot_number(210))
print(dot_number(3210))
print(dot_number(43210))
print(dot_number(543210))
print(dot_number(6543210))
print(dot_number(10000000000000))

print()
-- …alguns casos que não funcionam…
print(dot_number(-123))
print(dot_number(12.5))
print(dot_number(100000000000000))

Exit:

0
10
210
3.210
43.210
543.210
6.543.210
10.000.000.000.000

-.123
1.2.5
1e.+14
  • I think it would be nice to take the case treatment exceptional where the function fails, for example, very large numbers, etc.

  • I gave you +1, but I think you can only update if @vodka responds to what it wants to use this function for. I didn’t want to treat the negative and fractional cases because I don’t know the application of it. If it is e.g. to display monetary values, negative numbers have to appear as (123), nay -123; decimal numbers have to appear limited to two decimal places, and numbers 10 14 have to throw errors - as Lua uses doubles to represent numbers, they have accuracy worse than pennies.

0

function func(number)
    local number = number
    local decimal = number - math.floor(number)
    decimal = tonumber(tostring(decimal):sub(3, string.len(decimal)))
    number = tostring(math.floor(number)):reverse()
    for _ = 3, #number, 4 do
            number = number:sub(1, _) .. "." .. number:sub(_ + 1, #number)
    end
    return number:reverse() .. (decimal and "," .. decimal or "")
end
  • local number = number is redundant. Convert decimal to number as well...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.