Number refuses to divide - python

I have made a simple function called "Approx" which multiplies two numbers together then divides them by two. When I use the function by itself it works great but it seems in the hunk of code I have it doesn't divide the number in half and I have no idea why. This is my code where is the error and how can I fix it?
import math
def Approx(low,high):
base = low * high
return base/2
root = float(input("What to approx the sqrt of : "))
vague = float(input("How off can it be? : "))
wrong = True
oroot = root
root = math.floor(float(root))
trunk = root + 1
step = 0
while wrong:
if Approx(root,trunk) > oroot - vague and Approx(root,trunk) < oroot:
print("Done. " + str(step) + " steps taken.")
else:
if Approx(root,trunk) > oroot:
temproot = root
root = Approx(root,trunk)
trunk = temproot
step += 1
print("Step " + str(step) + " finished. Approx is " + str(Approx(root,trunk)))
else:
temptrunk = trunk
trunk = Approx(root,trunk)
root = trunk
step += 1
print("Step " + str(step) + " finished. Approx is " + str(Approx(root,trunk)))
if step > 50:
print("More than fifty steps required.")
wrong = False

It looks to me that it definitely does divide by two, it is just that dividing by two doesn't undo multiplying two large numbers together. For example, say you wanted to find the square root of 10. trunk is set to 11. Approx(root, trunk) is 10 * 11 / 2 = 55. This is set to root and trunk becomes the old root, 10. Now you have 55 and 10 instead of 10 and 11. Repeat this a few times and you end up with inf. Look more into the method you're trying to implement (is it the Babylonian method?) and see where your program and the method differ. That is likely the source of your woes, and not a lack of division.

Your function works the way you describe it, however I don't understand how you use it in the rest of the code.
It seems like you are trying to approximate square roots using a variant of Newton's method, but it's hard to understand how you implement it. Some variables in your code are not used (what is temptrunk for ?), and it's hard to determine if it's intended or a mistake.
If it is indeed the newton method you'd like to implement, you'll want to have an approximation function that converges to the target value. In order to do that, you compute the arithmetic mean of a guess and your target value divided by this guess (new_guess = mean([old_guess, target/old_guess])). Once you have that, you just need to compare the difference between new_guess and target, and once it reaches a given threshold (in your code, vague), you can break of the loop.
There are multiple ways to improve other aspects of your code:
I'd advise against using a sentinel value for breaking out of the loop, break statements are more explicit.
You can directly make a loop have maximum number of steps, with :
for step in range(MAX_STEPS):
guess = ... # try to guess
if abs(target - guess) < delta:
break
else:
print("Maximum steps reached.")
The else block will only be called if break is not reached.

Related

Using a BREAK statement to exit this while loop changes the value of the variable and gives incorrect answer. Need another way?

Question:
Write a program that implements Newton’s method to compute and display the square
root of a number entered by the user. The algorithm for Newton’s method follows:
Read x from the user
Initialize guess to x/2
While guess is not good enough do
Update guess to be the average of guess and x/guess
When this algorithm completes, guess contains an approximation of the square root. The quality of the approximation depends on how you define “good enough”. In the author’s solution, guess was considered good enough when the absolute value of the difference between guess ∗ guess and x was less than or equal to 10−12.
Solution:
x = int(input("Enter x: "))
guess = x/2
while guess != (abs(guess * guess - x <= 10 ** -12)):
guess = (guess + x/guess)/2
print(guess)
Note: if I add a break statement, it changes the value.
Ex: square root of 9 = 3 using the above solution.
but If I add a BREAK statement...
while guess != (abs(guess * guess - x <= 10 ** -12)):
guess = (guess + x/guess)/2
print(guess)
break
Enter x: 9
3.25
why does adding a break statement change the value of the guess variable? How do I terminate this loop without changing the value and simply print guess and exit loop?
endloop is not working and exit() seems to have the same effect. Any help will be greatly appreciated. Thank you !
if type(guess) != str:
break
I have also tried placing such a condition. same effect. prints incorrect value for guess.
This demonstrates the correct while condition:
x = int(input("Enter x: "))
guess = x/2
while abs(guess * guess - x) >= 10 ** -12:
guess = (guess + x/guess)/2
print(guess)
Output:
C:\tmp>python x.py
Enter x: 9
3.25
3.0096153846153846
3.000015360039322
3.0000000000393214
3.0
Here's a slightly different approach that uses an extra variable and thus a less complicated conditional expression. Also use a variable to determine the level of accuracy and also use that same variable to the presentation of the result.
x = float(input('X: '))
guess = x / 2
prev = x
DP = 4 # no. of decimal places accuracy
MARGIN = 10 ** -DP
while abs(guess - prev) > MARGIN:
prev = guess
guess = (guess + x / guess) / 2
print(f'{guess:.{DP}f}')
Example:
X: 17
4.1231

WAP in python script to input a multidigit number and find each of the number's factorial

The output shows a different result. Yes, the factorials of those numbers are right but the numbers outputted aren't right.
Here's the code:
input:
n = int(input("Enter a number: "))
s = 0
fact = 1
a = 1
for i in range(len(str(n))):
r = n % 10
s += r
n //= 10
while a <= s:
fact *= a
a += 1
print('The factorial of', s, 'is', fact)
Output:
Enter a number: 123
The factorial of 3 is 6
The factorial of 5 is 120
The factorial of 6 is 720
You're confusing yourself by doing it all in one logic block. The logic for finding a factorial is easy, as is the logic for parsing through strings character by character. However, it is easy to get lost in trying to keep the program "simple," as you have.
Programming is taking your problem, designing a solution, breaking that solution down into as many simple, repeatable individual logic steps as possible, and then telling the computer how to do every simple step you need, and what order they need to be done in to accomplish your goal.
Your program has 3 functions.
The first is taking in input data.
input("Give number. Now.")
The second is finding individual numbers in that input.
for character in input("Give number. Now."):
try:
int(character)
except:
pass
The third is calculating factorials for the number from step 2. I won't give an example of this.
Here is a working program, that is, in my opinion, much more readable and easier to look at than yours and others here. Edit: it also prevents a non numerical character from halting execution, as well as using only basic Python logic.
def factorialize(int_in):
int_out = int_in
int_multiplier = int_in - 1
while int_multiplier >= 1:
int_out = int_out * int_multiplier
int_multiplier -= 1
return int_out
def factorialize_multinumber_string(str_in):
for value in str_in:
print(value)
try:
print("The factorial of {} is {}".format(value, factorialize(int(value))))
except:
pass
factorialize_multinumber_string(input("Please enter a series of single digits."))
You can use map function to get every single digit from number:
n = int(input("Enter a number: "))
digits = map(int, str(n))
for i in digits:
fact = 1
a = 1
while a <= i:
fact *= a
a += 1
print('The factorial of', i, 'is', fact)
Ok, apart from the fact that you print the wrong variable, there's a bigger error. You are assuming that your digits are ever increasing, like in 123. Try your code with 321... (this is true of Karol's answer as well). And you need to handle digit zero, too
What you need is to restart the calculation of the factorial from scratch for every digit. For example:
n = '2063'
for ch in reversed(n):
x = int(ch)
if x == 0:
print(f'fact of {x} is 1')
else:
fact = 1
for k in range(2,x+1):
fact *= k
print(f'fact of {x} is {fact}')

Most efficient way to determine lowest valid number within a big range by only knowing whether your guess is too low

Let's assume you want to guess a certain number(x) within a big range in Python.
A simple external validation function, which you can call as many times as needed, will give you hints:
If the number being tested is equal to or higher than the lowest valid number, it will, in both cases, return True (you may not know explicitly if the number being tested is too high).
Else (if the number is too low) it will return False.
What would be the most efficient way to determine the smallest possible valid number? Is there a non-linear approach?
I don't know about most efficient, but here is a quite efficient algorithm. It first searches the order of magnitude by taking successive powers of 2. Then it uses dichotomy to narrow down the actual number:
num = 123
lowest = 0
guess = 1
check = lambda : guess >= num
i=0
# find order of magnitude
while not check():
i+=1
#print(guess)
lowest = guess
guess = guess*2
# find number
highest = guess
while lowest != highest-1:
i+=1
guess = (highest+lowest)//2
#print(lowest, guess, highest)
if check():
highest = guess
else:
lowest = guess
guess = highest
print(f'found {guess} in {i} steps')
Example with 123: found 123 in 13 steps
Example with 123456789: found 123456789 in 53 steps
NB. You can uncomment the print to see the intermediate steps
def validation(number, answer):
if answer > number:
return True
return False
The number parameter is the number you are trying to guess.

Recursive square root loop in python with a epsilon of .0001

I need help with a square root calculator.
The directions are as follows:
"You need to implement the Babylonian Method for computing square roots. Based on that core functionality, you are to write an interactive program that:
Prompts the user to enter an integer value above zero.
Checks to ensure that the value is indeed above zero. If not, the program displays an error message and asks for the input again.
Computes the square root of the value using the Babylonian Method outlined above.
Displays the square root to the user formatted to show exactly 3 decimal places (no more than 3, and no less than 3)."
I can't use the sqrt function. I'm getting really close but can't quite get to the right loop. Here's what I have so far
# Ask user if they would like to calculate a square root for a single number or range.
single = input("Enter 'single' or 'range' to solve for a single square root or a range of values, respectively: ")
# Set error message to let the user know 'range' calculation are not currently available.
if single == 'single' or 'Single':
# Ask user to enter a positive integer.
number = int(input("Enter a positive integer value: "))
# Set error message asking for valid number if user enters something other than a positive integer.
while number < 0:
print("Please enter a valid number.")
else:
# Choose epsilon
epsilon = .0001
# Choose estimate for the square root of x
estimate = 4
# Evaluate the estimate
while number - estimate > epsilon:
# Calculate the square root using the Babylonian Method.
estimate = (number + 1.0) / 2.0
second_estimate = (estimate + number / estimate) / 2.0
# Print the users selected value and its square root.
print("Value", " ", "Square Root")
print(" ", number, " ", format(second_estimate, '.3f'))
else:
# Tell user 'range' calculation are not currently available.
print("That function is not currently available.")
The condition for the while loop is wrong. number is 9 and estimate goes to 3. So you have to check number - estimate*estimate (take the absolute value because estimate converges to 3 from above for a starting value of 4). You dont need the first estimate according to Babylonian method on wikipedia.
Also estimate is always 5 in your code. (estimate = (number + 1.0) / 2.0 where number is always 9)
number = 9
epsilon = .0001
estimate = 4
while abs(number - estimate*estimate) > epsilon:
estimate = (estimate + number/estimate) / 2.0
print("Value", " ", "Square Root")
print(" ", number, " ", format(estimate, '.4f'))
Result:
Value Square Root
9 3.1250
Value Square Root
9 3.0025
Value Square Root
9 3.0000

Exhaustive Enumeration python

I need to create a program that finds the base and exponent of a single number given that the exponent is less than 7 and greater than 1. I am using python 2.7.
My code is as follows:
def determineRootAndPower(inputInteger):
pwr = 1
num = inputInteger
while (num) > 0 and (0 < pwr < 7):
inputInteger = inputInteger - 1
pwr = pwr + 1
num = num - 1
if int(num)**int(pwr) == inputInteger:
print(str(num) + (" to the power of ") + str(pwr) + (" equals ") + str(inputInteger) + ("!"))
else:
print("No base and root combination fit the parameters of this test")
Can anyone give me any general advice on this issue? Right now I am always receiving the 'else' statement which is not correct.
First, the reason you're always hitting the else is that you're doing the if check after the loop is over. So, instead of checking each value, you're just checking the very last values.
You want to print the "Yes" answer if any value matches, and the "No" only if all values fail. For that, you need to put the if inside the loop, and break as soon as you find the first success (unless you want to print all matches, instead of just the first one), and then the else becomes something you do only if you didn't find any of them.
You can use an else: with a while:, which gets run only if you didn't break anywhere. But many people find that confusing, so it might be simpler to just return instead of break on success, and just always print the failure message if you finish the loop.
Meanwhile, I think what you're hoping to do is handle all num values from inputNumber to 0, and, for each one, all pwr values from 1 to 7. To do that, you need a nested loop.
While we're at it, using a for loop is a whole lot easier than using a while loop around a variable that you initialize and +1 or -1 each time through.
Putting all of that together:
def determineRootAndPower(inputInteger):
for num in range(inputInteger, 0, -1):
for pwr in range(1, 7):
if int(num)**int(pwr) == inputInteger:
print(str(num) + (" to the power of ") + str(pwr) + (" equals ") + str(inputInteger) + ("!"))
return
print("No base and root combination fit the parameters of this test")
You can simplify this further.
What you really want is all combinations of any num in range, and any pwr in range. You don't care about how the nesting works, you just want all the combinations. In mathematical terms, you want to loop over the cartesian product of the two ranges. The function itertools.product does exactly that. So:
def determineRootAndPower(inputInteger):
for num, pwr in itertools.product(range(inputInteger, 0, -1), range(1, 7)):
if int(num)**int(pwr) == inputInteger:
print(str(num) + (" to the power of ") + str(pwr) + (" equals ") + str(inputInteger) + ("!"))
return
print("No base and root combination fit the parameters of this test")
As a side note, there are two things that make this code harder to read for no good reason.
First, if you want to print out an expression, it's a lot easier to use format (or %) than to manually convert things to strings and concatenate them together. Formatting lets you see what the output will look like, instead of having to figure it out, and it takes care of the stringifying and related stuff automatically.
Second, adding parentheses where they're not needed makes the code harder to read. The parentheses around your print expression makes your code look like Python 3, but it's actually Python 2. And the parentheses around each string inside the expression are even worse—at first glance, it looks like those are supposed to be inside the quotes. Even the parentheses in your test expression, (num) > 0 and (0 < pwr < 7), force the reader to pause—normally, parentheses like that are used to override the normal way operators combine together, so you have to think through what would be wrong with the normal num > 0 and 0 < pwr < 7 and how the parentheses make it different, only to eventually figure out that it's actually exactly the same.
Anyway, compare these two and see which one is easier to follow:
print "{} to the power of {} equals {}!".format(num, pwr, inputInteger)
print(str(num) + (" to the power of ") + str(pwr) + (" equals ") + str(inputInteger) + ("!"))

Categories

Resources