require "uchar" local function commatize(s, start = 1, step = 3, sep = ",") local function add_seps(n, dp) local lz = "" if !dp and n:startswith("0") and n != "0" then local k = n:lstrip("0") if k == "" then k = "0" end lz = "0":rep(#n - #k) n = k end if dp then n = n:reverse() end -- invert if after decimal point local i = #n - step + 1 while i >= 2 do n = n:sub(1, i - 1) .. sep .. n:sub(i) i -= step end if dp then n = n:reverse() end -- invert back return lz .. n end local function is_exponent(c) return c in "eEdDpP^∙x↑*⁰¹²³⁴⁵⁶⁷⁸⁹" end local t = uchar.of(s) local acc = start == 1 ? "" : t:sub(1, start - 1) local n = "" local dp = false for j = start, t:len() do local c = t:get(j) if c >= "0" and c <= "9" then n ..= t:get(j) if j == t:len() do if acc != "" and is_exponent(acc[-1]) then acc = s else acc ..= add_seps(n, dp) end end elseif n != "" then if acc != "" and is_exponent(acc[-1]) then acc = s break elseif t:get(j) != "." then acc ..= add_seps(n, dp) .. t:sub(j) break else acc ..= add_seps(n, dp) .. t:get(j) dp = true n = "" end else acc ..= t:get(j) end end print(s); print(acc); print() end commatize("123456789.123456789", 1, 2, "*") commatize(".123456789", 1, 3, "-") commatize("57256.1D-4", 1, 4, "__") commatize("pi=3.14159265358979323846264338327950288419716939937510582097494459231", 1, 5, " ") commatize("The author has two Z$100000000000000 Zimbabwe notes (100 trillion).", 1, 3, ".") local defaults = { "\"-in Aus$+1411.8millions\"", "===US$0017440 millions=== (in 2000 dollars)", "123.e8000 is pretty big.", "The land area of the earth is 57268900(29% of the surface) square miles.", "Ain't no numbers in this here words, nohow, no way, Jose.", "James was never known as 0000000007", "Arthur Eddington wrote: I believe there are 15747724136275002577605653961181555468044717914527116709366231425076185631031296 protons in the universe.", " $-140000±100 millions.", "6/9/1946 was a good year for some." } for defaults as d do commatize(d) end