B = require("bigint") local S = string.format function printf(...) io.write(string.format(...)) end function bc(exp) local cmd = string.format('echo "%s" | bc', exp) f = io.popen(cmd, 'r') s = f:read('*a') f:close() return s:gsub("\\", ""):gsub("\n", "") end ops = { ['+'] = function(a, b) return a + b end, ['-'] = function(a, b) return a - b end, ['*'] = function(a, b) return a * b end, ['/'] = function(a, b) return a / b end, ['^'] = function(a, b) return a ^ b end, } local signs = {"", "-", "+"} function test_op(a, b, op, msg) local sa = tostring(a):gsub("%s+", ""):gsub("^+", "") local sb = tostring(b):gsub("%s+", ""):gsub("^+", "") local r = ops[op](B(a), B(b)) local sr = tostring(r) local s = S('%s %s %s', sa, op, sb) local s2 = msg or S('%s %s %s', a, op, b) local br = bc(s) assert(sr==br, S("%s: '%s' != '%s'", s2, sr, br)) print(S("[PASSED] %s", s2)) end function test_four(a, b) print(("-"):rep(50)) print(S("A = '%s'", a)) print(S("B = '%s'", b)) for op in pairs(ops) do if op == '^' then goto continue end for _, s1 in ipairs(signs) do for _, s2 in ipairs(signs) do local sa = s1..a local sb = s2..b local ma = s1.."A" local mb = s2.."B" test_op(sa, sb, op, S("%s %s %s", ma, op, mb)) test_op(sb, sa, op, S("%s %s %s", mb, op, ma)) end end ::continue:: end end function test_divmod(a, b) local q, r = B(a):divmod(B(b)) local calculatedQuotient = tostring(q) local calculatedRemainder = tostring(r) local sq = S("%s / %s", a, b) local sr = S("%s %% %s", a, b) local expectedQuotient = bc(sq) local expectedRemainder = bc(sr) assert(calculatedQuotient==expectedQuotient, S("%s: '%s' != '%s'", sq, calculatedQuotient, expectedQuotient)) print(S("[PASSED] %s", sq)) assert(calculatedRemainder == expectedRemainder, S("%s: '%s' != '%s'", sr, calculatedRemainder, expectedRemainder)) print(S("[PASSED] %s", sr)) end test_four( "432094820938402398402983415987430593923832340", "234290830983245674250132908423290489320329209458645349721" ) test_four("123", "12") test_four( "10000000000000000000000000000000000000000000000000000000000000000", "99999999999999999999999999999999999999999999999999999999" ) test_divmod("12312321", "322") test_divmod("322", "12312321") test_op("2", "100", "^") test_op("5", "1024", "^")