python3 calculate N digits of PI python cut the long number - python

i need to write a script that get input from client of an number and i need to print back the PI number until client number
for example: client number is 52 --> 3.14159265358979323846264338327950288419716939937510
so far i write this:
sum = 0
for i in range(1, 1001):
sum += ((-1)**(i+1))*4 / ((i + i)*(i + i + 1)*(i + i + 2))
print(sum)
the issue is that python showing to me only the 17 decimals digits, and i expect to see the 1000 decimal digits.
there is a way to showing all the decimal digits based on the inputed range?
it's for school task, so i need to write is as simple as it can be.

I do not think it is possible to get a a float value with a 1000point precision.
Check https://stackoverflow.com/a/54967370/11152011 to calculate pi up to n-precision
You can then use the "decimal" library to use the string as a number.
The calculation of pi was taken from the above link.
import decimal
DIGITS = 1000
def pi_digits(x):
k,a,b,a1,b1 = 2,4,1,12,4
while x > 0:
p,q,k = k * k, 2 * k + 1, k + 1
a,b,a1,b1 = a1, b1, p*a + q*a1, p*b + q*b1
d,d1 = a/b, a1/b1
while d == d1 and x > 0:
yield int(d)
x -= 1
a,a1 = 10*(a % b), 10*(a1 % b1)
d,d1 = a/b, a1/b1
digits = [str(n) for n in list(pi_digits(DIGITS))]
str_pi='{}.{}'.format(digits.pop(0), "".join(digits)
context = decimal.Context(prec=100)
decimal.setcontext(context)
pi = decimal.Decimal(str_pi)
print(pi+5)
print(pi*20)

I don't know how accurate is this but for a small class assignment i guess do the following:
num=52 #input
pi=22/7;
print('{:.{}f}'.format(pi, num))

Related

Errors in Directly vs Recursively Calculating a given Fibonacci Number

I was bored at work and was playing with some math and python coding, when I noticed the following:
Recursively (or if using a for loop) you simply add integers together to get a given Fibonacci number. However there is also a direct equation for calculating Fibonacci numbers, and for large n this equation will give answers that are, frankly, quite wrong with respect to the recursively calculated Fibonacci number.
I imagine this is due to rounding and floating point arithmetic ( sqrt(5) is irrational after all), and if so can anyone point me into a direction on how I could modify the fibo_calc_direct function to return a more accurate result?
Thanks!
def fib_calc_recur(n, ii = 0, jj = 1):
#n is the index of the nth fibonacci number, F_n, where F_0 = 0, F_1 = 1, ...
if n == 0: #use recursion
return ii
if n == 1:
return jj
else:
return(fib_calc_recur(n -1, jj, ii + jj))
def fib_calc_direct(n):
a = (1 + np.sqrt(5))/2
b = (1 - np.sqrt(5))/2
f = (1/np.sqrt(5)) * (a**n - b**n)
return(f)
You could make use of Decimal numbers, and set its precision depending on the magninute of n
Not your question, but I'd use an iterative version of the addition method. Here is a script that makes both calculations (naive addition, direct with Decimal) for values of n up to 4000:
def fib_calc_iter(n):
a, b = 0, 1
if n < 2:
return n
for _ in range(1, n):
a, b = b, a + b
return b
from decimal import Decimal, getcontext
def fib_calc_decimal(n):
getcontext().prec = n // 4 + 3 # Choose a precision good enough for this n
sqrt5 = Decimal(5).sqrt()
da = (1 + sqrt5) / 2
db = (1 - sqrt5) / 2
f = (da**n - db**n) / sqrt5
return int(f + Decimal(0.5)) # Round to nearest int
# Test it...
for n in range(1, 4000):
x = fib_calc_iter(n)
y = fib_calc_decimal(n)
if x != y:
print(f"Difference found for n={n}.\nNaive method={x}.\nDecimal method={y}")
break
else:
print("No differences found")

Python removing first 3 digits in a number

Hopefully a simple one, I have a number, say 1234567.890 this number could be anything but will be this length.
How do I truncate the first 3 numbers so it turns into 4567.890?
This could be any number so subtracting 123000 will not work.
I'm working with map data in UTM coordinates (but that should not matter)
Example
x = 580992.528
y = 4275267.719
For x, I want 992.528
For y, I want 267.719
Note: y has an extra digit to the left of the decimal so 4 need removing
You can use slices for this:
x = 1234567.890
# This is still a float
x = float(str(x)[3:])
print(x)
Outputs:
4567.89
As [3:] gets the starts the index at 3 and continues to the end of the string
Update after your edit
The simplest way is to use Decimal:
from decimal import Decimal
def fmod(v, m=1000, /):
return float(Decimal(str(v)) % m)
print(fmod(x))
print(fmod(y))
Output
992.528
267.719
If you don't use string, you will have some problems with floating point in Python.
Demo:
n = 1234567.890
i = 0
while True:
m = int(n // 10**i)
if m < 1000:
break
i += 1
r = n % 10**i
Output:
>>> r
4567.889999999898
>>> round(r, 3)
4567.89
Same with Decimal from decimal module:
from decimal import Decimal
n = 1234567.890
n = Decimal(str(n))
i = 0
while True:
m = int(n // 10**i)
if m < 1000:
break
i += 1
r = n % 10**i
Output:
>>> r
Decimal('4567.89')
>>> float(r)
4567.89
This approach simply implements your idea.
int_len is the length of the integer part that we keep
sub is the rounded value that we will subtract the original float by
Code
Here is the code that implements your idea.
import math
def trim(n, digits):
int_len = len(str(int(n))) - digits # length of 4567
sub = math.floor(n / 10 **int_len) * 10**int_len
print(n - sub)
But as Kelly Bundy has pointed out, you can use modulo operation to avoid the complicated process of finding the subtrahend.
def trim(n, digits):
int_len = len(str(int(n))) - digits # length of 4567
print(n % 10**int_len)
Output
The floating point thing is a bit cursed and you may want to take Corralien's answer as an alternative.
>>> n = 1234567.890
>>> trim(n, 3)
4567.889999999898
def get_slice(number, split_n):
return number - (number // 10**split_n) * 10**split_n

How can I find out how much storage it would take to store every number between 1 and 2^100?

I am complete beginner when it comes to working with large numbers in code and I know this is definitely the wrong approach but this is what I started with.
import tqdm
try:
total = 0
for num in tqdm.tqdm(range(2**100), total=2**100):
total += len(bin(num)) - 2
finally:
with open('results.txt', 'w') as file:
file.write(f'{total=}')
The result I got was:
0%| | 87580807/1267650600228229401496703205376 [00:39<159887459362604133471:34:24, 2202331.37it/s]
Obviously this approach is going to take way too long. I know I could try making this multi-core but I don't think this is going to make much of a difference in the speed.
What are my options here?
Will using another language like C significantly increase the speed so that it will take days or hours instead of eons? Is there another approach/algorithm I can use?
Ok I figured it out. I used #jasonharper's approach.
So the code would be following:
total = 0
for power in range(1, 101):
total += ((int('1' * power, base=2) - int('1' + '0' * (power - 1), base=2)) + 1) * power
total was equal to 125497409422594710748173617332225, which represents the number of bytes needed to store every number between 1 and 2^100.
For some context it would take ≈425414947195.2363 times the total storage capacity of the Earth to store all numbers between 1 and 2^100.
Reference: https://www.zdnet.com/article/what-is-the-worlds-data-storage-capacity/
Interesting problem, but not all problems should be solved using brute force, there comes the part of the algorithm. Looking at your problem, it seems you want to count the number os bits required till some n. Now if we look closely,
number of bits total number of numbers we can represent
1 2**1 = 2
2 2**2 = 4
3 2**3 = 8
4 2**4 = 16
5 2**5 = 32
...
So the sum is like
1*2 + 2*2 + 3*2^2 + 4*2^3 + ...
= 1 + 1*2^0 + 2*2^1 + 3*2^2 + 4*2^3 + ...
= 1 + sum(k*2^(k-1)) with n from 1 to number of bits
= 1 + (k*2^k - 2^k +1)
= k*2^k - 2^k + 2
So there is a geometric progression visible. Using the summation methioned above you can determine the formula
import math
def log2(x):
return math.log(x) / math.log(2)
def count_the_total_number_of_bits_till(n):
neares_2_to_the_power = math.floor(log2(n))
actual_number_of_bits_required = math.ceil(log2(n))
sum_1 = ((neares_2_to_the_power * (2**neares_2_to_the_power)) - (2**neares_2_to_the_power) + 2)
extra_sum = ((n - 2**neares_2_to_the_power) * (actual_number_of_bits_required))
return sum_1 + extra_sum
count_the_total_number_of_bits_till(2**10)
what you were doing
sum_ = 0
for i in range(2**10):
#equivalent to
# count_the_total_number_of_bits_till(2**10)
sum_ += len(bin(i)[2:])
print(sum_)

Trigonometric Functions: How do I write Sine and Cosine function's code without using `math` module?

I have been writing code for a module I am making for my Discord Bot. I have been trying not to use any module as it is not helping in in importing stuff. So I thought I should write the code myself for both of them.
The problem here is that I don't really know how do we make them. I couldn't find them anywhere on the net as everywhere I only saw the use of math module which I don't want to use.
I don't know how do I work with them, so I want some help.
Thank You! :)
Using Taylor expansion you get an approximation up to the desired precision.
http://hyperphysics.phy-astr.gsu.edu/hbase/tayser.html
def pow(base, exponent):
return base ** exponent
def faktorial(n):
value = float(1)
for i in range(1, n+1):
value = value * i
return value
def cos(x):
x = x * 3.14/180
value = 1
sign = -1
n = 200 # precision
i = 2
while i < n:
value = value + (pow(x, i)/faktorial(i) * sign)
i = i + 2
sign = sign * -1
return value
def sin(x):
x = x * 3.14/180
value = x
sign = -1
n = 200 # precision
i = 3
while i < n:
value = value + (pow(x, i)/faktorial(i) * sign)
i = i + 2
sign = sign * -1
return value
pi = 3.1415926535897932384626433832795028841971 # Value of constant pi
def f(n): # Factorial Function
if n == 1 or n == 0:
return 1
else:
return n * f(n - 1)
def deg(x):
rad = x * pi/180
return rad
def sin(x): # Taylor Expansion of sinx
k = 0
sinx = 0
while x >= pi:
x -= pi
if pi > x > pi / 2:
x = pi - x
while k < 15:
sinx += (-1)**k * x**(2*k + 1) / f(2*k + 1)
k += 1
return sinx
def cos(x):
cosx = sin(pi / 2 - x)
return cosx
I improved the code now. Now it gives you accurate results of up to 14 decimal places. Also instead of writing full Taylor expression formula, I used a while loop to do that. While loop here acts as a summation function of maths. I also shorten the code inside cos(x). Instead of writing Taylor's expression here, I used a conversion formula of sinx to cosx. Which reduces the calculation process. I made a little change in the code. Now you can calculate sinx of huge number too with the same accuracy.

Python pi calculation?

I am a python beginner and I want to calculate pi. I tried using the Chudnovsky algorithm because I heard that it is faster than other algorithms.
This is my code:
from math import factorial
from decimal import Decimal, getcontext
getcontext().prec=100
def calc(n):
t= Decimal(0)
pi = Decimal(0)
deno= Decimal(0)
k = 0
for k in range(n):
t = ((-1)**k)*(factorial(6*k))*(13591409+545140134*k)
deno = factorial(3*k)*(factorial(k)**3)*(640320**(3*k))
pi += Decimal(t)/Decimal(deno)
pi = pi * Decimal(12)/Decimal(640320**(1.5))
pi = 1/pi
return pi
print calc(25)
For some reason this code yields the vakue of pi up to only 15 decimals as compared with the acceptable value. I tried to solve this by increasing the precision value; this increases the number of digits, but only the first 15 are still accurate. I tried changing the way it calculates the algorithm and it didn't work either. So my question is, is there something that can be done to this code to make it much more accurate or would I have to use another algorithm? I would appreciate help with this because I don't know how to operate with so many digits in python. I would like to be able to control the number of (correct) digits determined and displayed by the program -- whether 10, 100, 1000, etc.
It seems you are losing precision in this line:
pi = pi * Decimal(12)/Decimal(640320**(1.5))
Try using:
pi = pi * Decimal(12)/Decimal(640320**Decimal(1.5))
This happens because even though Python can handle arbitrary scale integers, it doesn't do so well with floats.
Bonus
A single line implementation using another algorithm (the BBP formula):
from decimal import Decimal, getcontext
getcontext().prec=100
print sum(1/Decimal(16)**k *
(Decimal(4)/(8*k+1) -
Decimal(2)/(8*k+4) -
Decimal(1)/(8*k+5) -
Decimal(1)/(8*k+6)) for k in range(100))
For people who come here just to get a ready solution to get arbitrary precision of pi with Python (source with a couple of edits):
import decimal
def pi():
"""
Compute Pi to the current precision.
Examples
--------
>>> print(pi())
3.141592653589793238462643383
Notes
-----
Taken from https://docs.python.org/3/library/decimal.html#recipes
"""
decimal.getcontext().prec += 2 # extra digits for intermediate steps
three = decimal.Decimal(3) # substitute "three=3.0" for regular floats
lasts, t, s, n, na, d, da = 0, three, 3, 1, 0, 0, 24
while s != lasts:
lasts = s
n, na = n + na, na + 8
d, da = d + da, da + 32
t = (t * n) / d
s += t
decimal.getcontext().prec -= 2
return +s # unary plus applies the new precision
decimal.getcontext().prec = 1000
pi = pi()
from decimal import *
#Sets decimal to 25 digits of precision
getcontext().prec = 25
def factorial(n):
if n<1:
return 1
else:
return n * factorial(n-1)
def plouffBig(n): #http://en.wikipedia.org/wiki/Bailey%E2%80%93Borwein%E2%80%93Plouffe_formula
pi = Decimal(0)
k = 0
while k < n:
pi += (Decimal(1)/(16**k))*((Decimal(4)/(8*k+1))-(Decimal(2)/(8*k+4))-(Decimal(1)/(8*k+5))-(Decimal(1)/(8*k+6)))
k += 1
return pi
def bellardBig(n): #http://en.wikipedia.org/wiki/Bellard%27s_formula
pi = Decimal(0)
k = 0
while k < n:
pi += (Decimal(-1)**k/(1024**k))*( Decimal(256)/(10*k+1) + Decimal(1)/(10*k+9) - Decimal(64)/(10*k+3) - Decimal(32)/(4*k+1) - Decimal(4)/(10*k+5) - Decimal(4)/(10*k+7) -Decimal(1)/(4*k+3))
k += 1
pi = pi * 1/(2**6)
return pi
def chudnovskyBig(n): #http://en.wikipedia.org/wiki/Chudnovsky_algorithm
pi = Decimal(0)
k = 0
while k < n:
pi += (Decimal(-1)**k)*(Decimal(factorial(6*k))/((factorial(k)**3)*(factorial(3*k)))* (13591409+545140134*k)/(640320**(3*k)))
k += 1
pi = pi * Decimal(10005).sqrt()/4270934400
pi = pi**(-1)
return pi
print "\t\t\t Plouff \t\t Bellard \t\t\t Chudnovsky"
for i in xrange(1,20):
print "Iteration number ",i, " ", plouffBig(i), " " , bellardBig(i)," ", chudnovskyBig(i)

Categories