-- 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))