Search code examples
luasumprojectfactorial

Project Euler -Prob. #20 (Lua)


http://projecteuler.net/problem=20 I've written code to figure out this problem, however, it seems to be accurate in some cases, and inaccurate in others. When I try solving the problem to 10 (answer is given in question, 27) I get 27, the correct answer. However, when I try solving the question given (100) I get 64, the incorrect answer, as the answer is something else.

Here's my code:

function factorial(num)
    if num>=1 then
        return num*factorial(num-1)
    else
        return 1
    end
end

function getSumDigits(str)
    str=string.format("%18.0f",str):gsub(" ","")
    local sum=0
    for i=1,#str do
        sum=sum+tonumber(str:sub(i,i))
    end
    return sum
end

print(getSumDigits(tostring(factorial(100))))

64

Since Lua converts large numbers into scientific notation, I had to convert it back to standard notation. I don't think this is a problem, though it might be.

Is there any explanation to this?


Solution

  • Unfortunately, the correct solution is more difficult. The main problem here is that Lua uses 64bit floating point variables, which means this applies.

    Long story told short: The number of significant digits in a 64bit float is much too small to store a number like 100!. Lua's floats can store a maximum of 52 mantissa bits, so any number greater than 2^52 will inevitably suffer from rounding errors, which gives you a little over 15 decimal digits. To store 100!, you'll need at least 158 decimal digits. The number calculated by your factorial() function is reasonably close to the real value of 100! (i.e. the relative error is small), but you need the exact value to get the right solution.

    What you need to do is implement your own algorithms for dealing with large numbers. I actually solved that problem in Lua by storing each number as a table, where each entry stores one digit of a decimal number. The complete solution takes a little more than 50 lines of code, so it's not too difficult and a nice exercise.