// Pi calculation using Machin's formula // pi/4 = 4*arctan(1/5) - arctan(1/239) #import #include // Calculate arctan(1/x) using Taylor series with arbitrary precision // arctan(1/x) = 1/x - 1/(3*x^3) + 1/(5*x^5) - ... void arctan(mpz_t result, unsigned long x, unsigned long decimals) { mpz_t scale, term, x_squared, temp; mpz_init(scale); mpz_init(term); mpz_init(x_squared); mpz_init(temp); // scale = 10^(decimals + 10) mpz_ui_pow_ui(scale, 10, decimals + 10); // x_squared = x * x mpz_ui_pow_ui(x_squared, x, 2); // term = scale / x mpz_fdiv_q_ui(term, scale, x); // result = 0 mpz_set_ui(result, 0); int sign = 1; unsigned long n = 1; while (mpz_cmp_ui(term, 0) > 0) { // result += sign * term / n mpz_fdiv_q_ui(temp, term, n); if (sign > 0) { mpz_add(result, result, temp); } else { mpz_sub(result, result, temp); } // term = term / x² mpz_fdiv_q(term, term, x_squared); n += 2; sign = -sign; } mpz_clear(scale); mpz_clear(term); mpz_clear(x_squared); mpz_clear(temp); } // Calculate pi using Machin's formula NSString* calculatePi(int decimals) { if (decimals < 1) { decimals = 100; } mpz_t arctan5, arctan239, pi; mpz_init(arctan5); mpz_init(arctan239); mpz_init(pi); // Machin's formula: pi/4 = 4*arctan(1/5) - arctan(1/239) arctan(arctan5, 5, decimals); arctan(arctan239, 239, decimals); // pi = 16*arctan(1/5) - 4*arctan(1/239) mpz_mul_ui(arctan5, arctan5, 16); mpz_mul_ui(arctan239, arctan239, 4); mpz_sub(pi, arctan5, arctan239); // Convert to string char* piStr = mpz_get_str(NULL, 10, pi); NSString* result = [NSString stringWithUTF8String:piStr]; free(piStr); // Format output if (decimals == 0) { return @"3"; } // Pad with zeros if needed NSString* padded = result; if ([result length] < decimals + 1) { NSUInteger zerosNeeded = decimals + 1 - [result length]; padded = [@"0" stringByPaddingToLength:zerosNeeded withString:@"0" startingAtIndex:0]; padded = [padded stringByAppendingString:result]; } // Insert decimal point NSString* beforeDecimal = [padded substringWithRange:NSMakeRange(0, 1)]; NSString* afterDecimal = [padded substringWithRange:NSMakeRange(1, [padded length] - 1)]; // Pad or truncate to desired length if ([afterDecimal length] < decimals) { afterDecimal = [afterDecimal stringByPaddingToLength:decimals withString:@"0" startingAtIndex:0]; } else { afterDecimal = [afterDecimal substringWithRange:NSMakeRange(0, decimals)]; } mpz_clear(arctan5); mpz_clear(arctan239); mpz_clear(pi); return [NSString stringWithFormat:@"%@.%@", beforeDecimal, afterDecimal]; } int main(int argc, const char* argv[]) { @autoreleasepool { int decimals = 100; if (argc > 1) { decimals = atoi(argv[1]); if (decimals < 1) { decimals = 100; } } NSString* pi = calculatePi(decimals); printf("%s\n", [pi UTF8String]); } return 0; }