-- Simple BigInt implementation using base 10^9 local BigInt = {} BigInt.__index = BigInt function BigInt.new(value) local self = setmetatable({}, BigInt) if type(value) == "number" then if value == 0 then self.digits = {0} else self.digits = {math.abs(value)} end else self.digits = {0} end return self end function BigInt:add(other) local carry = 0 local maxLen = math.max(#self.digits, #other.digits) for i = 1, maxLen do local a = self.digits[i] or 0 local b = other.digits[i] or 0 local sum = a + b + carry self.digits[i] = sum % 1000000000 carry = math.floor(sum / 1000000000) end if carry > 0 then table.insert(self.digits, carry) end end function BigInt:subtract(other) local borrow = 0 for i = 1, #self.digits do local a = self.digits[i] local b = other.digits[i] or 0 local diff = a - b - borrow if diff < 0 then diff = diff + 1000000000 borrow = 1 else borrow = 0 end self.digits[i] = diff end -- Remove leading zeros while #self.digits > 1 and self.digits[#self.digits] == 0 do table.remove(self.digits) end end function BigInt:multiply(scalar) local result = BigInt.new(0) result.digits = {} local carry = 0 for i = 1, #self.digits do local prod = self.digits[i] * scalar + carry result.digits[i] = prod % 1000000000 carry = math.floor(prod / 1000000000) end if carry > 0 then table.insert(result.digits, carry) end return result end function BigInt:divide(divisor) local result = BigInt.new(0) result.digits = {} local remainder = 0 for i = #self.digits, 1, -1 do local cur = remainder * 1000000000 + self.digits[i] result.digits[i] = math.floor(cur / divisor) remainder = cur % divisor end -- Remove leading zeros while #result.digits > 1 and result.digits[#result.digits] == 0 do table.remove(result.digits) end return result end function BigInt:isZero() return #self.digits == 1 and self.digits[1] == 0 end function BigInt:toString() local result = "" for i = #self.digits, 1, -1 do if i == #self.digits then result = result .. self.digits[i] else result = result .. string.format("%09d", self.digits[i]) end end return result end -- Power of 10 local function pow10(exp) local result = BigInt.new(1) for i = 1, exp do result = result:multiply(10) end return result end -- Calculate arctan(1/x) using Taylor series local function arctan(x, decimals) local scale = pow10(decimals + 10) local x_squared = x * x local term = scale:divide(x) local result = BigInt.new(0) local n = 0 while not term:isZero() do local divisor = 2 * n + 1 local contrib = term:divide(divisor) if n % 2 == 0 then result:add(contrib) else result:subtract(contrib) end term = term:divide(x_squared) n = n + 1 end return result end -- Calculate pi using Machin's formula local function calculate_pi(decimals) local atan1_5 = arctan(5, decimals) local atan1_239 = arctan(239, decimals) -- pi = 16*arctan(1/5) - 4*arctan(1/239) local pi16 = atan1_5:multiply(16) local pi4 = atan1_239:multiply(4) pi16:subtract(pi4) local pi_str = pi16:toString() -- Format with decimal point local result = "3." local start = 2 for i = 0, decimals - 1 do if start + i <= #pi_str then result = result .. string.sub(pi_str, start + i, start + i) else result = result .. "0" end end return result end -- Main local decimals = 100 if #arg > 0 then decimals = tonumber(arg[1]) or 100 end print(calculate_pi(decimals))