lualuajit

Reliable way of getting the exact decimals from any number


I'm having problem returning spesific amount of decimal numbers from this function, i would like it to get that info from "dec" argument, but i'm stuck with this right now. Edit: Made it work with the edited version bellow but isn't there a better way?

local function remove_decimal(t, dec)
    if type(dec) == "number" then
        for key, num in pairs(type(t) == "table" and t or {}) do
            if type(num) == "number" then
                local num_to_string = tostring(num)
                local mod, d = math.modf(num)
                -- find only decimal numbers
                local num_dec = num_to_string:sub(#tostring(mod) + (mod == 0 and num < 0 and 3 or 2))

                if dec <= #num_dec then
                    -- return amount of deciamls in the num by dec
                    local r = d < 0 and "-0." or "0."
                    local r2 = r .. num_dec:sub(1, dec)

                    t[key] = mod + tonumber(r2)
                end
            end
        end
    end
    return t
end

By passing the function bellow i want a result like this:

result[1] > 0.12
result[2] > -0.12
result[3] > 123.45
result[4] > -1.23

local result = remove_decimal({0.123, -0.123, 123.456, -1.234}, 2)

print(result[1])
print(result[2])
print(result[3])
print(result[4])

I tried this but it seems to only work with one integer numbers and if number is 12.34 instead of 1.34 e.g, the decimal place will be removed and become 12.3. Using other methods

local d = dec + (num < 0 and 2 or 1)
local r = tonumber(num_to_string:sub(1, -#num_to_string - d)) or 0

Solution

  • A good approach is to find the position of the decimal point (the dot, .) and then extract a substring starting from the first character to the dot's position plus how many digits you want:

    local function truncate(number, dec)
        local strnum = tostring(number)
        local i, j = string.find(strnum, '%.')
        
        if not i then
            return number
        end
        
        local strtrn = string.sub(strnum, 1, i+dec)
        return tonumber(strtrn)
    end
    

    Call it like this:

    print(truncate(123.456, 2))
    print(truncate(1234567, 2))
    
    123.45
    1234567
    

    To bulk-truncate a set of numbers:

    local function truncate_all(t, dec)
        for key, value in pairs(t) do
            t[key] = truncate(t[key], dec)
        end
        return t
    end
    

    Usage:

    local result = truncate_all({0.123, -0.123, 123.456, -1.234}, 2)
    
    for key, value in pairs(result) do
        print(key, value)
    end
    
    1   0.12
    2   -0.12
    3   123.45
    4   -1.23