Lua - format integer

I would like to format a number that looks like this: β€œ1,234” or β€œ1,234,432” or β€œ123,456,789”, you get this idea. I tried to do it as follows;

function reformatint(i) local length = string.len(i) for v = 1, math.floor(length/3) do for k = 1, 3 do newint = string.sub(mystring, -k*v) end newint = ','..newint end return newint end 

As you can see, I have an unsuccessful attempt, the problem is that I cannot decide what is to blame, because the program in which I run this refuses to inform me of an error.

+6
source share
4 answers

Here is a function that takes into account negative numbers and fractional parts:

 function format_int(number) local i, j, minus, int, fraction = tostring(number):find('([-]?)(%d+)([.]?%d*)') -- reverse the int-string and append a comma to all blocks of 3 digits int = int:reverse():gsub("(%d%d%d)", "%1,") -- reverse the int-string back remove an optional comma and put the -- optional minus and fractional part back return minus .. int:reverse():gsub("^,", "") .. fraction end assert(format_int(1234) == '1,234') assert(format_int(1234567) == '1,234,567') assert(format_int(123456789) == '123,456,789') assert(format_int(123456789.1234) == '123,456,789.1234') assert(format_int(-123456789.) == '-123,456,789') assert(format_int(-123456789.1234) == '-123,456,789.1234') assert(format_int('-123456789.1234') == '-123,456,789.1234') print('All tests passed!') 
+10
source

Ok, let’s take it top to bottom. First of all, it does not work, because you have a reference error:

  ... for k = 1, 3 do newint = string.sub(mystring, -k*v) -- What is 'mystring'? end ... 

Most likely you want i be there, not mystring .

Secondly, when replacing mystring with i , errors will be fixed, it will still work incorrectly.

 > =reformatint(100) ,100 > =reformatint(1) ,000 

This is clearly not the case. It seems that what you are trying to do is go through the line and create a new line with a comma added. But there are a couple of problems ...

 function reformatint(i) local length = string.len(i) for v = 1, math.floor(length/3) do for k = 1, 3 do -- What is this inner loop for? newint = string.sub(mystring, -k*v) -- This chops off the end of -- your string only end newint = ','..newint -- This will make your result have a ',' at -- the beginning, no matter what end return newint end 

With some refinement, you can get a function that works.

 function reformatint(integer) for i = 1, math.floor((string.len(integer)-1) / 3) do integer = string.sub(integer, 1, -3*ii) .. ',' .. string.sub(integer, -3*i-i+1) end return integer end 

The above function is working correctly. However, it is rather confusing ... Could make it more readable.

As an additional note, a quick Google search finds a function that has already been done for this:

 function comma_value(amount) local formatted = amount while true do formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2') if (k==0) then break end end return formatted end 
+3
source

You can do without loops:

 function numWithCommas(n) return tostring(math.floor(n)):reverse():gsub("(%d%d%d)","%1,") :gsub(",(%-?)$","%1"):reverse() end assert(numWithCommas(100000) == "100,000") assert(numWithCommas(100) == "100") assert(numWithCommas(-100000) == "-100,000") assert(numWithCommas(10000000) == "10,000,000") assert(numWithCommas(10000000.00) == "10,000,000") 

The second gsub is necessary to avoid - 100 is generated.

+1
source

I remember discussing this on the LΓ–VE forums ... let me find it ...

Found it !

This will work with whole positive goals:

 function reformatInt(i) return tostring(i):reverse():gsub("%d%d%d", "%1,"):reverse():gsub("^,", "") end 

In the link above you can read implementation details.

+1
source

Source: https://habr.com/ru/post/917839/


All Articles