Skip to content

Instantly share code, notes, and snippets.

@chuyqa
Last active March 14, 2025 17:13
Show Gist options
  • Save chuyqa/6fadba763fb1d2d0e014a2a929af2a52 to your computer and use it in GitHub Desktop.
Save chuyqa/6fadba763fb1d2d0e014a2a929af2a52 to your computer and use it in GitHub Desktop.
Computing Pi via Leibniz, Nilakantha, Machin's formulas
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"id": "49785bab-5586-4551-93b3-23e9dd1b9c33",
"metadata": {},
"source": [
"## 3 Approaches to computing Pi\n",
"\n",
"**Leibniz** - 4_000_000 terms and does not converge for 12 digits in ~75ms\n",
"\n",
"**Nilakantha** - 10_000 terms to converge for 12 digits in ~870 µs\n",
" \n",
"**Machin's Arctan** - 10 terms to fully converge for 12 digits in ~55 µs\n"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "d960d559-5af6-463c-a8c0-936933656282",
"metadata": {},
"outputs": [],
"source": [
"# Target: first 12 digits of π\n",
"true_pi = 3.141592653589793"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "80995941-8c12-4ef4-8e12-3105d50e6804",
"metadata": {},
"outputs": [],
"source": [
"def leibniz_pi(terms=5_000_000):\n",
" \"\"\"Leibniz formula: π/4 = 1 - 1/3 + 1/5 - 1/7 + ...\n",
" This converges EXTREMELY slow, and will still have an error ratio at above 4m\n",
" \"\"\"\n",
" pi_approx = 0\n",
" sign = 1\n",
" for i in range(terms):\n",
" denominator = 2 * i + 1\n",
" pi_approx += sign * (1 / denominator)\n",
" sign = -sign\n",
" if i % 200_000 == 0 and i > 0:\n",
" current = 4 * pi_approx\n",
" print(f\"Leibniz ({i} terms): {current:.12f}\")\n",
" return 4 * pi_approx"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "a268a4b3-3716-4e5d-9381-514d5be117e6",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Leibniz Method:\n",
"Leibniz (200000 terms): 3.141597653565\n",
"Leibniz (400000 terms): 3.141595153583\n",
"Leibniz (600000 terms): 3.141594320254\n",
"Leibniz (800000 terms): 3.141593903588\n",
"Leibniz (1000000 terms): 3.141593653589\n",
"Leibniz (1200000 terms): 3.141593486922\n",
"Leibniz (1400000 terms): 3.141593367875\n",
"Leibniz (1600000 terms): 3.141593278589\n",
"Leibniz (1800000 terms): 3.141593209145\n",
"Leibniz (2000000 terms): 3.141593153589\n",
"Leibniz (2200000 terms): 3.141593108135\n",
"Leibniz (2400000 terms): 3.141593070256\n",
"Leibniz (2600000 terms): 3.141593038205\n",
"Leibniz (2800000 terms): 3.141593010732\n",
"Leibniz (3000000 terms): 3.141592986923\n",
"Leibniz (3200000 terms): 3.141592966090\n",
"Leibniz (3400000 terms): 3.141592947707\n",
"Leibniz (3600000 terms): 3.141592931367\n",
"Leibniz (3800000 terms): 3.141592916747\n",
"Leibniz (4000000 terms): 3.141592903590\n",
"Leibniz (4200000 terms): 3.141592891685\n",
"Leibniz (4400000 terms): 3.141592880862\n",
"Leibniz (4600000 terms): 3.141592870981\n",
"Leibniz (4800000 terms): 3.141592861923\n",
"Final Leibniz : 3.141592453590\n",
"\n",
"True π (12digit): 3.141592653590\n",
"\n",
"CPU times: user 351 ms, sys: 0 ns, total: 351 ms\n",
"Wall time: 351 ms\n"
]
}
],
"source": [
"%%time\n",
"print(\"Leibniz Method:\")\n",
"leibniz_result = leibniz_pi()\n",
"\n",
"print(f\"Final Leibniz : {leibniz_result:.12f}\\n\")\n",
"print(f\"True π (12digit): {true_pi:.12f}\\n\")"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "98f8ea54-813a-49f7-9003-206f6c544bd3",
"metadata": {},
"outputs": [],
"source": [
"def nilakantha_pi(terms=10000):\n",
" \"\"\"Nilakantha series: π = 3 + 4/(2*3*4) - 4/(4*5*6) + ...\"\"\"\n",
" pi = 3.0\n",
" sign = 1\n",
" for n in range(2, terms * 2, 2):\n",
" denominator = n * (n + 1) * (n + 2)\n",
" pi += sign * (4 / denominator)\n",
" sign = -sign\n",
" if n % 1500 == 0:\n",
" print(f\"Nilakantha ({n//2} terms): {pi:.12f}\")\n",
" return pi"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "d3e1117c-d798-4a42-bdf7-2ea6f0b6a1f7",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Nilakantha Method:\n",
"Nilakantha (750 terms): 3.141592653000\n",
"Nilakantha (1500 terms): 3.141592653516\n",
"Nilakantha (2250 terms): 3.141592653568\n",
"Nilakantha (3000 terms): 3.141592653581\n",
"Nilakantha (3750 terms): 3.141592653585\n",
"Nilakantha (4500 terms): 3.141592653587\n",
"Nilakantha (5250 terms): 3.141592653588\n",
"Nilakantha (6000 terms): 3.141592653589\n",
"Nilakantha (6750 terms): 3.141592653589\n",
"Nilakantha (7500 terms): 3.141592653589\n",
"Nilakantha (8250 terms): 3.141592653589\n",
"Nilakantha (9000 terms): 3.141592653589\n",
"Nilakantha (9750 terms): 3.141592653590\n",
"Final Nilakantha: 3.141592653590\n",
"\n",
"True π (12digit): 3.141592653590\n",
"\n",
"CPU times: user 892 µs, sys: 0 ns, total: 892 µs\n",
"Wall time: 850 µs\n"
]
}
],
"source": [
"%%time\n",
"print(\"Nilakantha Method:\")\n",
"nilakantha_result = nilakantha_pi()\n",
"print(f\"Final Nilakantha: {nilakantha_result:.12f}\\n\")\n",
"print(f\"True π (12digit): {true_pi:.12f}\\n\")"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "9bd4e04b-67a1-4db5-8863-f64119359409",
"metadata": {},
"outputs": [],
"source": [
"def arctan_pi(terms=10):\n",
" \"\"\"Machin's formula: π = 4 * (4 * arctan(1/5) - arctan(1/239))\"\"\"\n",
" def arctan(x, n_terms):\n",
" result = 0\n",
" for n in range(n_terms):\n",
" power = 2 * n + 1\n",
" result += (-1)**n * (x**power) / power\n",
" return result\n",
" \n",
" # Calculate arctan values once\n",
" atan_1_5 = arctan(1/5, terms)\n",
" atan_1_239 = arctan(1/239, terms)\n",
" \n",
" # Print progress using partial sums\n",
" for t in range(2, terms + 1, 2):\n",
" partial_5 = arctan(1/5, t)\n",
" partial_239 = arctan(1/239, t)\n",
" partial_pi = 4 * (4 * partial_5 - partial_239)\n",
" print(f\"Arctan ({t} terms): {partial_pi:.12f}\")\n",
" \n",
" # Final result\n",
" return 4 * (4 * atan_1_5 - atan_1_239)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "9c671c02-514a-49fb-8fac-0d1dc5ad1d9f",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Arctan Method:\n",
"Arctan (2 terms): 3.140597029326\n",
"Arctan (4 terms): 3.141591772182\n",
"Arctan (6 terms): 3.141592652615\n",
"Arctan (8 terms): 3.141592653589\n",
"Arctan (10 terms): 3.141592653590\n",
"Final Arctan : 3.141592653590\n",
"\n",
"True π (12digit): 3.141592653590\n",
"\n",
"CPU times: user 114 µs, sys: 10 µs, total: 124 µs\n",
"Wall time: 112 µs\n"
]
}
],
"source": [
"%%time\n",
"print(\"Arctan Method:\")\n",
"arctan_result = arctan_pi()\n",
"print(f\"Final Arctan : {arctan_result:.12f}\\n\")\n",
"print(f\"True π (12digit): {true_pi:.12f}\\n\")"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ba2fc2d6-6b50-47b5-8f0b-7f0f08c3118e",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": ".conda-pwner-runtime",
"language": "python",
"name": "conda-env-.conda-pwner-runtime-py"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.8"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment