How to get these results in Python? - python

I am trying to fix a problem I have, but I can't get the answers right.
"""
Given is the following heading of a function to calculate the cosines.
def cosines (x, number_of_terms):
# x is a float; number_of_terms is an int
This method calculates the cosines of x with the series
x - x^3/3! + x^5/5! - x^7/7! + x^9/9! - ...
x^n is the notation for "x to the power n" and n! is the notation for "the factorial of n".
The number of terms that should be calculated is given by the parameter number_of_terms.
Implement this method.
Do this without using any functions from the module math. Assume: number_of_terms >= 1.
"""
So, what I did is this:
def cosines(x, number_of_terms):
sign = 1
result = 0.0
counter = x
denominator = 1.0
for i in range (number_of_terms, number_of_terms+1):
fracture = counter / denominator
term = sign * fracture
result += term
counter *= x
denominator *= i
sign = - sign
return result
first = cosines(90.0, 1)
second = cosines(90.0, 4)
third = cosines(90.0, 8)
print "should be 30.000000: %f" % first
print "should be -4546255.714286: %f" % second
print "should be -7167780281079.437000: %f" % third
This is the result I get:
---BEGIN TEST---
should be 30.000000: 90.000000
should be -4546255.714286: 90.000000
should be -7167780281079.437000: 90.000000
----END TEST----
What am I doing wrong?

I corrected your code and changed the names of the function to 'sines' as that is what the math reflects:
def factorial(n):
if n == 0:
return 1
else:
return n * factorial(n-1)
def sines(x_in_degrees, number_of_terms):
# Convert to radians
#import math
#x = math.radians(x_in_degrees)
x = x_in_degrees * 3.141592653589793/180.0
sign = 1
result = 0.0
p = 1
for i in range(1, number_of_terms+1):
num = x**p
denom = factorial(p)
temp = sign * num / denom
#temp = sign * math.pow(x, p) / math.factorial(p)
result = result + temp
sign = - sign
p = p + 2
return result
first = sines(90.0, 1)
second = sines(90.0, 4)
third = sines(90.0, 8)
print "Result with one term: %f" % first
print "Result with four terms: %f" % second
print "Result with eight terms: %f" % third

(EDITED) As pointed out in the comments, your code needs to
Work with angles in radians, not degrees
Implement the correct power series for cosine
Interpreting "number of terms" as the number of relevant terms in the power series you want computed, below is an example computing the cosine of 45 degrees or pi/4 radians.
If you want to compute the factorial in the loop, the key to making the code work is that that the computation of a term is done only for even iterations, to match the cosine power series.
def cosines(x, number_of_terms):
sign = 1
result = 1
counter = x
denominator = 1.0
# Counting the 1 in the cosine power series as the first "term"
terms_computed = 1
# skip computing for iterations not relevant to the power series
iterations = 1
while terms_computed < number_of_terms:
iterations += 1
counter *= x
denominator *= iterations
if iterations %2 == 0:
terms_computed += 1
sign = - sign
fracture = counter / denominator
term = sign * fracture
result += term
print 'input %d, number of relevant terms computed %d'%(number_of_terms,terms_computed)
return result
pi= 3.1415926
angle = pi/4.
print 'angle in radians ',angle
first = cosines(angle, 1)
second = cosines(angle, 2)
third = cosines(angle, 4)
fourth = cosines(angle, 8)
fifth = cosines(angle, 10)
print "first %f" % first
print "second %f" % second
print "third %f" % third
print "fourth %f" % fourth
print "fifth %f" % fifth
Results:
angle in radians 0.78539815
input 1, number of relevant terms computed 1
input 2, number of relevant terms computed 2
input 4, number of relevant terms computed 4
input 8, number of relevant terms computed 8
input 10, number of relevant terms computed 10
first 1.000000
second 0.691575
third 0.707103
fourth 0.707107
fifth 0.707107

Related

Dynamically change floating point precision in Python

I'm trying to write a program that calculates pi with different accuracies and prints out the number and the time elapsed. I want to print the result with the current accuracy each time. I used print('pi = %*f'%(i, pi)) where i is my current floating point accuracy. This made the program round up the number to the i decimal digit. I'm attaching a picture showing my results running the same algorithm but changing output from:
print (" pi = ", pi, " =with ", i-1, " decimal points accuracy= in: ", (-1)*t, "sec")
to:
print (" pi = %.*f"%(i, pi), " =with ", i-1, " decimal points accuracy= in: ", (-1)*t, "sec")
This is my full code:
import time
accuracy = 4
for i in range(1,accuracy + 1):
pi = 0
prevPi = 1
x = 0
t = time.time()
while abs((pi * 4) - prevPi) > 10**((-1)*(i+1)):
#while x < lim:
prevPi = pi * 4
pi += (((-1)**(x))/(1+(2*x)))
#print(abs((pi * 4) - prevPi))
x += 1
pi *= 4
t -= time.time()
print (" pi = %.*f"%(i, pi), " =with ", i-1, " decimal points accuracy= in: ", (-1)*t, "sec")
How do I print the number with i decimal digits WITHOUT rounding?
You could approach your problem by defining function which truncates your number. That function could take two arguments:
number which you want to truncate,
position, at which it would drop all following values.
def truncate(number, position):
'''Return number with dropped decimal places past specified position.'''
return number - number%(10**position)
For instance if you would want number 3.14 truncated to 3.1, you should call following:
truncate(3.14, -1)
Also I modified your code so it would be simpler and match PEP 8 coding conventions. Therefore now it has increased variable naming clarity and better code formatting.
#!/usr/bin/env python3
'''Module for different pi accuracies calculation time comparison.'''
from time import time
def truncate(number, position):
'''Return number with dropped decimal places past specified position.'''
return number - number%(10**position)
def calculate_pi(accuracy):
'''Return pi with certain floating point accuracy.'''
previous_pi = 0
current_pi = 4
iterator = 1
while abs(current_pi - previous_pi) > 10 ** (accuracy-1):
previous_pi = current_pi
current_pi += 4 * ((-1)**iterator) / (1+(2*iterator))
iterator += 1
return truncate(current_pi, accuracy)
def calculation_speed_comparison(max_accuracy):
'''Print comparison of different accuracy pi calculation time.'''
for current_accuracy in range(max_accuracy+1):
calculation_time = time()
current_pi = calculate_pi(-current_accuracy)
calculation_time -= time()
print('pi = {} with {} decimal points accuracy in {} seconds.'.format(
current_pi, current_accuracy, -calculation_time))
calculation_speed_comparison(4)
Output to this code remains very similar to original one:
pi = 3.0 with 0 decimal points accuracy in 3.266334533691406e-05 seconds.
pi = 3.1 with 1 decimal points accuracy in 0.00016045570373535156 seconds.
pi = 3.14 with 2 decimal points accuracy in 0.0014882087707519531 seconds.
pi = 3.141 with 3 decimal points accuracy in 0.01430201530456543 seconds.
pi = 3.1415 with 4 decimal points accuracy in 0.1466822624206543 seconds.

Python User defined number of output decimals

I want to make a small python script to calculate pi to N number of decimal points and then only output that number of decimals. I don't know how to change the print statement to dynamically limit the number of outputted decimals. Here's my code.
#!python
import math
N = input("Enter the number of digits of pi you would like to compute: ")
runs = math.ceil(N/math.log(2))
a_0 = 1.0
b_0 = 1.0/(2.0**(1.0/2.0))
t_0 = 1.0/4.0
p_0 = 1.0
for x in xrange(1,N):
a = (a_0 + b_0)/2
b = (a_0*b_0)**(1.0/2.0)
t = t_0 - p_0*(a_0 - a)**2
p = 2*p_0
pi = ((a_0 + b_0)**2)/(4*t)
print pi
a_0 = a
b_0 = b
t_0 = t
p_0 = p
print 'Pi to %d number of digits is: ' % (N)
print "%0" N "d\n" % pi
I know my last print statement isn't how you implement this feature, but it gives an idea of how you might do it in something kinda like C.
I just want that last print statement to output pi to N number of digits.

Can anyone tell me why is my code showing the wrong value of pi?

Here's a picture of my output:
inptTol = float(input("Enter the tolerance: "))
print()
term = 1
divNum = 3
npower = 1
sumPi = 0.0
count = 0
while abs(term) > inptTol:
sumPi += term
term = -term/(divNum * (3**npower))
divNum += 2
npower += 1
count += 1
sumPi = math.sqrt(12) * sumPi
pythonPi = math.pi
approxError = abs (sumPi - pythonPi)
print("The approximate value of pi is %.14e\n" \
" Python's value of pi is %.14e\n"
"The error in the approximation of pi is %.6e\n"
"The number of terms used to calculate the value of pi is %g " %
(sumPi, pythonPi, approxError, count))
These are the values it is is showing:
The approximate value of pi is 3.08770957930231e+00
Python's value of pi is 3.14159265358979e+00
I want it to show me this :
The approximate value of pi is 3.14159265358979
Python's value of pi is 3.14159265358979
I think you're missing signal. Apparently you tried to do this but changing the previous term signal and using it on the next term.
See my code, i tried to do like his. What do you think?
import math
inptTol = float(input("The tolerance: "))
signal = 1.0
term = 1.0
divNum = 3.0
npower = 1.0
sumPi = 0.0
count = 0.0
while inptTol < abs(term):
signal *= -1.0
sumPi += term
term = signal / (divNum * (3.0 ** npower))
divNum += 2.0
npower += 1.0
count += 1.0
sumPi *= math.sqrt(12.0)
pythonPi = math.pi
approxError = abs(sumPi - pythonPi)
print("The approximate value of pi is %.14f\n" \
" Python's value of pi is %.14f\n"
"The error in the approximation of pi is %.6e\n"
"The number of terms used to calculate the value of pi is %g " %
(sumPi, pythonPi, approxError, count))
As for me problem is because you change term value. it has to be 1 or -1 - sign.
My version - I use for loop
import math
terms_number = float(input("Enter terms number: "))
sign = 1
divNum = 1
npower = 0
sumPi = 0.0
count = 0
for x in range(terms_number):
sumPi += sign/(divNum * (3**npower))
# values for next term
sign = -sign
divNum += 2
npower += 1
count += 1
sumPi = math.sqrt(12) * sumPi
pythonPi = math.pi
approxError = abs (sumPi - pythonPi)
print("The approximate value of pi is %.14e\n" \
" Python's value of pi is %.14e\n"
"The error in the approximation of pi is %.6e\n"
"The number of terms used to calculate the value of pi is %g " %
(sumPi, pythonPi, approxError, count))
Result for 7 terms
The approximate value of pi is 3.14167431269884e+00
Python's value of pi is 3.14159265358979e+00
The error in the approximation of pi is 8.165911e-05
The number of terms used to calculate the value of pi is 7
Result for 15 terms
The approximate value of pi is 3.14159265952171e+00
Python's value of pi is 3.14159265358979e+00
The error in the approximation of pi is 5.931921e-09
The number of terms used to calculate the value of pi is 15
EDIT: version with your while loop
import math
inptTol = float(input("Enter the tolerance: "))
term = 1
sign = 1
divNum = 1
npower = 0
sumPi = 0.0
count = 0
while abs(term) > inptTol:
term = sign/(divNum * (3**npower))
sumPi += term
# values for next term
sign = -sign
divNum += 2
npower += 1
count += 1
sumPi = math.sqrt(12) * sumPi
pythonPi = math.pi
approxError = abs (sumPi - pythonPi)
print("The approximate value of pi is %.14e\n" \
" Python's value of pi is %.14e\n"
"The error in the approximation of pi is %.6e\n"
"The number of terms used to calculate the value of pi is %g " %
(sumPi, pythonPi, approxError, count))
Your term calculation is wrong:
term = -term/(divNum * (3**npower))
Say term is currently -1/(3*3). This line won't set term to 1/(5 * 3**2); it'll set term to 1/(3*3) / (5 * 3**2). You're reducing term way more than you're supposed to.
It looks like your trying to define term[i+1] in terms of term[i]. If you change that line to:
term = -term*(divNum-2)/(divNum * 3)
then the recursive definition will produce the appropriate values. This definition will flip the sign, remove the old odd number in the denominator, add the new odd number in the denominator, and add a factor of 3 in the denominator.
You can use this kind of pattern to generate the denominator for the terms in your approximation. I'll let you do the division and summation, and the final multiplication by sqrt(12)
print [(-1)**(i%2)*(3**(i)*(1+i*2)) for i in range(0,10)]
You are using e as the number format which means:
Exponent notation. Prints the number in scientific notation using the letter ā€˜eā€™ to indicate the exponent.
If you want fixed point output you can use f:
Fixed point. Displays the number as a fixed-point number.
Other formats/options can be found in the documentation
Found the bug in your code. Each term is calculated using the previous term as the numerator, when really you just want alternating -1 and 1s. Changing the formula for calculating term fixes the issue:
term = ((-1)**npower)/(divNum * (3**npower))
Demo

Modulo is not processing correctly

I cannot seem to make sure that the python modulo function is working properly, I have tried various numbers and cannot seem to get a correct division.
ISBN Number
print """
Welcome to the ISBN checker,
To use this program you will enter a 10 digit number to be converted to an International Standard Book Number
"""
ISBNNo = raw_input("please enter a ten digit number of choice")
counter = 11 #Set the counter to 11 as we multiply by 11 first
acc = 0 #Set the accumulator to 0
Begin the loop, multiply each digit in the string by a decrimenting counter
We need to treat the number as a string to obtain each placement
for i in ISBNNo:
print str(i) + " * " + str(counter)
acc = acc + (int(i) * counter) #cast value a integer and multiply by counter
counter -= 1 #decrement counter
print "Total = " + str(acc)
Mod by 11 (divide and take remainder
acc = acc % 11
print "Mod by 11 = " + str(acc)
take it from 11
acc = 11 - acc
print "subtract the remainder from 9 = " + str(acc)
concatenate with string
ISBNNo = ISBNNo + str(acc)
print "ISBN Number including check digit is: " + ISBNNo
Your code is mostly correct, except for some issues:
1) You're trying to compute the checksum (last digit) if the ISBN. This means that you should only take 9 digits into consideration:
ISBNNo = raw_input("please enter a ten digit number of choice")
assert len(ISBNNo) == 10, "ten digit ISBN number is expected"
# ...
for i in ISBNNo[0:9]: # iterate only over positions 0..9
# ...
2) Also there should be a special case here:
ISBNNo = ISBNNo + str(acc)
print "ISBN Number including check digit is: " + ISBNNo
You're doing modulo-11, so acc can be equal to 10. ISBN mandates that "X" should be used as the last "digit" in this case, which could be written as:
ISBNNo = ISBNNo + (str(acc) if acc < 10 else 'X')
Here's the fixed code, with example number from Wikipedia: http://ideone.com/DaWl6y
In response to comments
>>> 255 // 11 # Floor division (rounded down)
23
>>> 255 - (255//11)*11 # Remainder (manually)
2
>>> 255 % 11 # Remainder (operator %)
2
(Note: I'm using // which stands for floor division. In Python 2, you could simply use / too because you're dividing integers. In Python 3, / is always true division and // is floor division.)

leading number groups between two numbers

(Python) Given two numbers A and B. I need to find all nested "groups" of numbers:
range(2169800, 2171194)
leading numbers: 21698XX, 21699XX, 2170XX, 21710XX, 217110X, 217111X,
217112X, 217113X, 217114X, 217115X, 217116X, 217117X, 217118X, 2171190X,
2171191X, 2171192X, 2171193X, 2171194X
or like this:
range(1000, 1452)
leading numbers: 10XX, 11XX, 12XX, 13XX, 140X, 141X, 142X, 143X,
144X, 1450, 1451, 1452
Harder than it first looked - pretty sure this is solid and will handle most boundary conditions. :) (There are few!!)
def leading(a, b):
# generate digit pairs a=123, b=456 -> [(1, 4), (2, 5), (3, 6)]
zip_digits = zip(str(a), str(b))
zip_digits = map(lambda (x,y):(int(x), int(y)), zip_digits)
# this ignores problems where the last matching digits are 0 and 9
# leading (12000, 12999) is same as leading(12, 12)
while(zip_digits[-1] == (0,9)):
zip_digits.pop()
# start recursion
return compute_leading(zip_digits)
def compute_leading(zip_digits):
if(len(zip_digits) == 1): # 1 digit case is simple!! :)
(a,b) = zip_digits.pop()
return range(a, b+1)
#now we partition the problem
# given leading(123,456) we decompose this into 3 problems
# lows -> leading(123,129)
# middle -> leading(130,449) which we can recurse to leading(13,44)
# highs -> leading(450,456)
last_digits = zip_digits.pop()
low_prefix = reduce(lambda x, y : 10 * x + y, [tup[0] for tup in zip_digits]) * 10 # base for lows e.g. 120
high_prefix = reduce(lambda x, y : 10 * x + y, [tup[1] for tup in zip_digits]) * 10 # base for highs e.g. 450
lows = range(low_prefix + last_digits[0], low_prefix + 10)
highs = range(high_prefix + 0, high_prefix + last_digits[1] + 1)
#check for boundary cases where lows or highs have all ten digits
(a,b) = zip_digits.pop() # pop last digits of middle so they can be adjusted
if len(lows) == 10:
lows = []
else:
a = a + 1
if len(highs) == 10:
highs = []
else:
b = b - 1
zip_digits.append((a,b)) # push back last digits of middle after adjustments
return lows + compute_leading(zip_digits) + highs # and recurse - woohoo!!
print leading(199,411)
print leading(2169800, 2171194)
print leading(1000, 1452)
def foo(start, end):
index = 0
is_lower = False
while index < len(start):
if is_lower and start[index] == '0':
break
if not is_lower and start[index] < end[index]:
first_lower = index
is_lower = True
index += 1
return index-1, first_lower
start = '2169800'
end = '2171194'
result = []
while int(start) < int(end):
index, first_lower = foo(start, end)
range_end = index > first_lower and 10 or int(end[first_lower])
for x in range(int(start[index]), range_end):
result.append(start[:index] + str(x) + 'X'*(len(start)-index-1))
if range_end == 10:
start = str(int(start[:index])+1)+'0'+start[index+1:]
else:
start = start[:index] + str(range_end) + start[index+1:]
result.append(end)
print "Leading numbers:"
print result
I test the examples you've given, it is right. Hope this will help you
This should give you a good starting point :
def leading(start, end):
leading = []
hundreds = start // 100
while (end - hundreds * 100) > 100:
i = hundreds * 100
leading.append(range(i,i+100))
hundreds += 1
c = hundreds * 100
tens = 1
while (end - c - tens * 10) > 10:
i = c + tens * 10
leading.append(range(i, i + 10))
tens += 1
c += tens * 10
ones = 1
while (end - c - ones) > 0:
i = c + ones
leading.append(i)
ones += 1
leading.append(end)
return leading
Ok, the whole could be one loop-level deeper. But I thought it might be clearer this way. Hope, this helps you...
Update :
Now I see what you want. Furthermore, maria's code doesn't seem to be working for me. (Sorry...)
So please consider the following code :
def leading(start, end):
depth = 2
while 10 ** depth > end : depth -=1
leading = []
const = 0
coeff = start // 10 ** depth
while depth >= 0:
while (end - const - coeff * 10 ** depth) >= 10 ** depth:
leading.append(str(const / 10 ** depth + coeff) + "X" * depth)
coeff += 1
const += coeff * 10 ** depth
coeff = 0
depth -= 1
leading.append(end)
return leading
print leading(199,411)
print leading(2169800, 2171194)
print leading(1000, 1453)
print leading(1,12)
Now, let me try to explain the approach here.
The algorithm will try to find "end" starting from value "start" and check whether "end" is in the next 10^2 (which is 100 in this case). If it fails, it will make a leap of 10^2 until it succeeds. When it succeeds it will go one depth level lower. That is, it will make leaps one order of magnitude smaller. And loop that way until the depth is equal to zero (= leaps of 10^0 = 1). The algorithm stops when it reaches the "end" value.
You may also notice that I have the implemented the wrapping loop I mentioned so it is now possible to define the starting depth (or leap size) in a variable.
The first while loop makes sure the first leap does not overshoot the "end" value.
If you have any questions, just feel free to ask.

Categories

Resources