Fun project calculating PI using integer maths.

Hi all...

As you know I have garnered a great interest in using integer maths to do some fixed point calculations.
Here is my next incarnation, calculating PI to 3 and 12 decimal places using 2 of the simplest of series to obtain the value.
First is the Gregory-Leibniz series which is notoriously SSLLOOWW but would be useful for 16 bit systems.
Second is the Nilakantha series which is much, MUCH faster and used to show the 12 places of decimals in 64 bit systems.

Leibniz formula for π - Wikipedia
Pi - Wikipedia

This carries on from my previous fun pieces on here.
Read the code for more information.

#!/bin/sh

# #!/usr/local/bin/dash
# PI.sh
# PI to 3, (Gregory-Leibniz series), and 12, (Nilakantha`s series), decimal places:-
# 3.141 [592653589]

# A FUN exercise to see if it is possible to get PI to at least 12 places of decimal.
# In 16 bit mode 3, (possibly 4), places of decimal is the absolute limit.
# In normal 32 bit integer mode 8 places of decimal is the absolute limit.
# In 64 bit integer mode 18 places of decimal is the absolute limit.
# Fully POSIX compliant!
#
# Important note: POSIX maths does not include "x**y", (x to the power of y),
# hence the bizarre usage of the variable POWER inside the script. This is
# to account for (-1)**(POWER) inside the functions for both of these
# examples to switch the sign of each term in the series.
#
# Issued to www.unix.com as CC0, Public Domain.

clear
echo 'Start...'
echo 'Using integer maths only and fully POSIX compliant!'

# Simplest of all, Gregory-Leibniz series - very, VERY SLOW,
# and errors may occur beyond the 6th decimal place in 32 bit mode.
# This example is for 16 bit systems.
# PI=(4/1)-(4/3)+(4/5)-(4/7)+(4/9)-(4/11)+(4/13)-...
echo ''
echo 'Gregory-Leibniz series, (very, VERY slow).'
PI_APPROX=0
SWITCH_SIGN=0
POWER=1
K=1
LOOP=0
while [ ${LOOP} -le 200 ]
do
    if [ ${PI_APPROX} -eq 3142 ]
    then
        break
    fi
    if [ $(( POWER%2 )) -eq 0 ]
    then
        SWITCH_SIGN="-1"
    else
        SWITCH_SIGN="1"
    fi
    PI_APPROX=$(( PI_APPROX+(1*(SWITCH_SIGN))*(4000/K) ))
    POWER=$(( POWER+1 ))
    K=$(( K+2 ))
    LOOP=$(( LOOP+1 ))
done
printf "16 bit; PI to 3 decimal places = %.3f...\n" "${PI_APPROX}e-3"
echo "Number of loops = ${LOOP}."
echo ''

# Nilakantha's series, much, MUCH faster...
# PI=3+(4/(2�-3�-4))�'(4/(4�-5�-6))+(4/(6�-7�-8))�'(4/(8�-9�-10))+...
echo 'Nilakantha`s series, (much, MUCH faster).'
PI_APPROX=3000000000000
SWITCH_SIGN=1
POWER=0
K=2
LOOP=0
while [ ${LOOP} -le 2500 ]
do
    if [ ${PI_APPROX} -eq 3141592653589 ]
    then
        break
    fi
    if [ $(( POWER%2 )) -eq 0 ]
    then
        SWITCH_SIGN="1"
    else
        SWITCH_SIGN="-1"
    fi
    PI_APPROX=$(( PI_APPROX+(1*(SWITCH_SIGN))*(4000000000000/(K*(K+1)*(K+2))) ))
    POWER=$(( POWER+1 ))
    K=$(( K+2 ))
    LOOP=$(( LOOP+1 ))
done
printf "64 bit; PI to 12 decimal places = %.12f...\n" "${PI_APPROX}e-12"
echo "Number of loops = ${LOOP}."
echo ''
echo 'Stop...'

Results OSX 10.14.3, default bash terminal, originally calling dash.

Start...
Using integer maths only and fully POSIX compliant!

Gregory-Leibniz series, (very, VERY slow).
16 bit; PI to 3 decimal places = 3.142...
Number of loops = 144.

Nilakantha`s series, (much, MUCH faster).
64 bit; PI to 12 decimal places = 3.141592653589...
Number of loops = 2426.

Stop...
AMIGA:amiga~/Desktop/Code/Shell> _

Enjoy...

Bazza...

1 Like