This question already has answers here:
Formatting floats without trailing zeros
(21 answers)
Closed 1 year ago.
I just started coding for about a month now. I'm making my first actually useful program that finds the root/s of a quadratic equation. It's almost done and it needs a little bit more fixing but there's one thing I can't really seem to figure out.
Here's my code:
import math
filler = "Empty Here"
print("Please enter in integer coefficients a, b, and c")
operator_for_bx = " + "
operator_for_c = " + "
a = int(input("a="))
b = int(input("b="))
c = int(input("c="))
discriminant = b*b - 4*a*c
determinant = discriminant
root_positive = str(float((-b + math.sqrt(discriminant)) / (2*a)))
root_negative = str(float((-b - math.sqrt(discriminant)) / (2*a)))
root_one_real_sol = str(float((-b)/(2*a)))
if b < 0:
operator_for_bx = " - "
if c < 0:
operator_for_c = " - "
if a == 1:
print("Your quadratic equation is: " + "x^2" + operator_for_bx + str(abs(b)) + "x" + operator_for_c + str(abs(c)))
elif a == -1:
print("Your quadratic equation is: " + "-x^2" + operator_for_bx + str(abs(b)) + "x" + operator_for_c + str(abs(c)))
else:
print("Your quadratic equation is: " + str(a) + "x^2" + operator_for_bx + str(abs(b)) + "x" + operator_for_c + str(abs(c)))
if determinant == 0:
print("It only has 1 real solution.")
print("It's root is: " + root_one_real_sol + ".")
elif determinant >= 1:
print("It has 2 real solutions.")
print("The roots are: " + root_positive + " and " + root_negative + ".")
else:
print("It has 2 complex but not real solutions.")
You see, occasionally the answer I get for the roots turns out into a whole number. Which is fine and all, but the thing is I had to let it out as a float or else decimal numbers wouldn't work. So if ever a whole number would appear, it'd say "x.0",(x being whatever number came out) and I don't want a decimal point to be shown if it's a whole number so, how do should I make it so?
(Also yes I know this won't work for quadratic equations with 2 complex but not real solutions and I think I can fix that by myself- maybe I'll use the Try and Except stuff)
Here's an example code that could accomplish that:
x = [1.0, 2.0, 2.5, 3.5]
new_x = [int(i) if int(i) == i else i for i in x]
print(new_x)
Output:
[1, 2, 2.5, 3.5]
This uses list comprehension, but the main idea I want to show is that in order to check if something has nothing after "." you can just check that the int version of it is equal to the floating point version.
I need to use bisection search to approximate the square root of a number. I wrote the following code but it only works when my number is greater than 1. If it's a decimal like 0.36 in the following example, my code is just not working. Could you please look at it and give me suggestions on why and how to fix it?
x = 0.36
dp = 0.01
numGuesses = 0
low = 0.0
high = x
ans = (high + low)/2.0
while abs(ans**2 - x) >= dp:
print("low ="+ str(low) + "high = " + str(high) + " ans = " + str(ans))
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print("numGuesses =" + str(numGuesses))
print(str(ans) + "is close to square root of" + str(x))
If the number is less than 0 then the root of that number will be greater than that. So you should start from 1. Try this
x = 0.36
dp = 0.01
numGuesses = 0
low = 0.0
high = x
ans = 0
if x> 1:
ans = (high + low)/2.0
else:
ans = 1
while abs(ans**2 - x) >= dp:
print("low ="+ str(low) + "high = " + str(high) + " ans = " + str(ans))
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print("numGuesses =" + str(numGuesses))
print(str(ans) + "is close to square root of" + str(x))
So I'm entirely new to coding and I'm taking the MIT Openwarecourse to get started (and I'm using the book Introducing to Computation and Programming using Python)
Also since I'm new here I'm a bit afraid that my question is low quality so please point out if you think I should improve the manner on how I asks questions.
At 3.4 I'm given the code:
x = int(input("Please enter an integer: "))
epsilon = 0.01
numGuesses = 0
low = -100
high = max(1.0, x)
ans = (high + low)/2.0
while abs(ans**2 -x) >= epsilon:
print ("low = ", low, "High=", high, "ans=", ans)
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print ("numGuesses =", numGuesses)
print (ans, "Is close to square root of", x)
So what I tried to do first is understand each line of the code and what it exactly does. I've been given the hint: "Think about changing low to ensure that the answer lies within the region being searched.)
I've tried to change low to a negative number and I tried to add if low is less than 0, then low = -low like this:
x = int(input("Please enter an integer: "))
epsilon = 0.01
numGuesses = 0
low = 0.0
if low < 0:
low = -low
high = max(1.0, x)
ans = (high + low)/2.0
while abs(ans**2 -x) >= epsilon:
print ("low = ", low, "High=", high, "ans=", ans)
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print ("numGuesses =", numGuesses)
print (ans, "Is close to square root of", x)
However I'm probably taking a wrong approach...
You were very close, to convert the program to find an approximation to the cube root of both negative and positive numbers you have to only change the range in which your algorithm is searching.
To find cube root of positive numbers:
x = 8
epsilon = 0.01
numGuesses = 0
high = max(1.0, x)
low = 0.0
ans = (high + low) / 2.0
while abs((pow(ans,3)- x)) >= epsilon:
print("low ",low," ,high ",high," ans ",ans)
numGuesses += 1
if pow(ans,3) < x:
low = ans
else:
high = ans
ans = (high + low) /2.0
print("numguesses , = "+str(numGuesses))
print(str(ans)+"is close to square root of x "+ str(x))
The algorithm searches between low and high.
Suppose a user enters a number say 8 implies high = 8 and low = 0.0 and then it performs the search and will output 2.0, if user enters a negative number say -8 then high = 1.0 and low = 0.0 which don't appear to be right,the correct limit should be i.e [-8,0) (cube root of a negative number is negative) "ignoring complex roots", in this case high = 0 and low = -8.
You can do it by a simple if else statement.
x = 8
epsilon = 0.01
numGuesses = 0
high = max(1.0, x)
low = 0.0
if x < 0:
low = x
else:
None
ans = (high + low) / 2.0
while abs((pow(ans,3)- x)) >= epsilon:
print("low ",low," ,high ",high," ans ",ans)
numGuesses += 1
if pow(ans,3) < x:
low = ans
else:
high = ans
ans = (high + low) /2.0
print("numguesses , = "+str(numGuesses))
print(str(ans)+"is close to square root of x "+ str(x))
I hope this is a beginner friendly answer.
To solve the problem I used the min function and compared x to 1.0, then extracted the lowest value. I did this because it is the direct inverse of extracting the initial high value.
x = -25
epsilon = 0.01
num_guesses = 0
low = min(x, 1.0)
high = max(1.0, x)
ans = (high + low) / 2.0
while abs(ans**3 - x) >= epsilon:
print('low =', low, 'high =', high, 'ans =', ans)
num_guesses += 1
if ans**3 < x:
low = ans
else:
high = ans
ans = (high + low) / 2.0
print('num guesses =', num_guesses)
print(ans, 'is close to cube root of', x)
I wrote an alternative code that allows negatives of square, cube, etc roots while keeping the core of OP's code unchanged:
number = int(input('Number? '))
x = abs(number)
root = int(input('Root? '))
epsilon = 0.01
numGuesses = 0
low = 0.0
high = max(1.0, x)
ans = (high + low)/2.0
while abs(ans**root - x) >= epsilon:
print('low =', low, 'high =', high, 'ans =', ans)
numGuesses += 1
if ans**root < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print('numGuesses =', numGuesses)
if number < 0:
if root%2 == 1:
ans = -ans
else:
ans = str(ans)+'i'
print(ans, 'is close to square root of', number)
It takes the input number as absolute and checks its signal after the calculation is performed. It also adds 'i' in case of even roots of negative numbers.
x = int(input("Please enter an integer: "))
epsilon = 0.01
numGuesses = 0
low = -abs(x)
high = max(1.0, x)
ans = (high + low)/2.0
while abs(ans**2 -x) >= epsilon:
print ("low = ", low, "High=", high, "ans=", ans)
numGuesses += 1
if ans**2 < x:
low = ans
else:
high = ans
ans = (high + low)/2.0
print ("numGuesses =", numGuesses)
print (ans, "Is close to square root of", x)
x = int(input('Enter the number you want to find the root of: '))
root = int(input('Enter the power number: '))
epsilon = 0.01
numGuesses = 0
low = 0.0
high = x #note that u removed max()
guess = (high + low)/2.0 #note u changed ans to guess
while abs(abs(guess**root) - abs(x)) >= epsilon:
print('low =', low, 'high =', high, 'ans =', guess)
numGuesses += 1
if abs(guess**root) < abs(x):
low = guess
else:
high = guess
guess = (high + low)/2.0
print('numGuesses =', numGuesses)
print(guess, 'is close to root of', x)
This works well and there are not a lot of changes from the OG code
Your algorithm is a numerical search through dichotomy method applied to X^2-x=0, it converges (quite fast actually) towards the solution X=sqrt(x) as long as low is lower than the solution, and high is higher than the solution.
In your case x is always higher than sqrt(x) and 0 is always lower than sqrt(x).
The answer will always be in the region being searched,you can lower epsilon as much as you want. There is no point in changing the initialisation of low. If you lower it to negative values, it will only require a few more step, roughly log2(abs(low))
change
ans**2
to
ans**3
and your algorithm converges to the cubic root of x.
The cubic root of negative numbers is not well defined, I guess what they mean is the cubic root of the absolute value, multiplied by -1. So (-3)^3 =-9
If x<0, replace x by abs(x), run the algorithm and return the solution multiplied by -1.
This:
low = 0.0
if low < 0:
low = -low
literally does nothing. You set low = 0 and then check if it's less than 0 (which it isn't). Also, 0 is both positive and negative, so changing its sign does nothing.
I'm afraid I don't understand the problem entirely, but it looks like high and low are bounds within which you expect the square/cubed root to be?
If x is negative then you want to make sure your lower bound can encompass it. Maybe setting low = x would help?
I really am not sure how to explain my question in a title; a graphic will be best.
I've been given this problem as something to play around with in class, so far only one person has managed to achieve a solution, and it's a very complex one.
While I've spoken to him (The best we can manage, his english isn't great), I'd like to come up with my own solution, but I need some pointers, or at least new ideas..
The problem is this:
n=5
0 3 5 5 3 0
3 5 5 3
5 5
5 5
3 5 5 3
0 3 5 5 3 0
With 'n' being an input value.
So far I've got this;
#!/usr/bin/env python3
while True:
n = int(input("Enter a size : "))
z = "+"
for i in range(n*2): # ROWS
for j in range(n*2): # COLUMNS
if i == 0 or j == 0 or i == n*2 - 1 or j == n*2 - 1: # OUTLINE
print(z, end=" ")
elif j < n-i: # TOP LEFT
print(z, end=" ")
elif j >= n+i or i >= n+j: # TOP RIGHT + BOTTOM LEFT
print(z, end=" ")
elif j >= n*2-i+n-1 and i >= n*2-j+n-1: # BOTTOM RIGHT
print(z, end=" ")
else:
print(" ", end=" ")
print()
Whitch outputs this;
Enter a size : 5
+ + + + + + + + + +
+ + + + + + + +
+ + + + + +
+ + + +
+ +
+ +
+ + + +
+ + + + + +
+ + + + + + + +
+ + + + + + + + + +
The next step is to replace "z" with an equation for the places in the box I guess. But I've no idea where to start (And my math is a little rusty)
Taking a guess, I suppose this is what you mean:
def square(n):
def row(i, n):
l = [str(x) if x <= n else ' ' for x in range(i, i+n)]
return l + l[::-1]
top = [row(i, n) for i in range(1, n+1)]
return '\n'.join(' '.join(r) for r in (top + top[::-1]))
while True:
n = int(input("> "))
print(square(n))
I solved it, and not in a way I was expecting, tbh. I'd call it a dirty hack.
#!/usr/bin/env python
__author__ = "Luke Jones"
__copyright__ = "Copyleft, do what you want with it"
__license__ = "GPL"
__version__ = "0.0.1"
while True:
startV = int(input("Enter a size : "))
array1=[]
array2=[]
for i in range(1,startV+1,2):
array1.append(i)
array2 = list(array1)
array2.reverse()
n = len(array1)
for i in range(n*2): # ROWS
for j in range(n*2): # COLUMNS
if j < n-i: # TOP LEFT
print(array1[j+i], end=" ")
elif j >= n+i: # TOP RIGHT
print(array2[j-n-i], end=" ")
elif i >= n+j: # BOTTOM LEFT
print(array2[i-n-j], end=" ")
elif i >= n*2-j+n-1 and not i >= n*2-j+n:
#print("X",end=" ")
for q in range(n*2-j):
print(array2[q], end=" ")
else:
print(" ", end=" ")
print()
I'm working out of a book that teaches the principles of computer programming through Python. One of the finger exercises asks that I: Write a program that asks a user to input an integer and prints two integers, root and pwr, such that 0 < pwr < 6 and root^pwr is equal to the integer entered by the user. If no such pair of integers exists, it should print a message to that effect. I wrote a program that does what this asks. I just have one question about testing the equation with the numbers of a list. Here's my code:
x = int(raw_input('Enter an integer: '))
root = 0
pwr = [1,2,3,4,5]
listnum = 0
for root in range(0, x + 1):
while pow(root, pwr[listnum]) < x:
root += 1
if pow(root, pwr[listnum]) == x:
print str(root) + '^' + str(pwr[listnum]) + ' = ' + str(x)
break
listnum += 1
if pow(root, pwr[listnum]) == x:
print str(root) + '^' + str(pwr[listnum]) + ' = ' + str(x)
break
listnum += 1
if pow(root, pwr[listnum]) == x:
print str(root) + '^' + str(pwr[listnum]) + ' = ' + str(x)
break
listnum += 1
if pow(root, pwr[listnum]) == x:
print str(root) + '^' + str(pwr[listnum]) + ' = ' + str(x)
break
listnum += 1
if pow(root, pwr[listnum]) == x:
print str(root) + '^' + str(pwr[listnum]) + ' = ' + str(x)
break
listnum = 0
if pow(root, pwr[listnum]) == x:
break
else:
print 'No combinations within parameters exist'
I'd like to know how to test if pow(root, pwr[listnum]) < x for all 5 increments without having to repeat listnum += 1...if...break repeatedly. If the question is unclear I can try to elaborate more. I've seen a question regarding this exact problem, but none of them clearly answer the specific question I have, so I have no intention of reposting a question. If any other suggestions are to be made, they are much appreciated. Thanks!
Here's one way to do what you're after:
def find(x):
for root in range(x + 1):
for pwr in range(1, 6):
y = pow(root, pwr)
if y > x:
break
if y == x:
return root, pwr
return None
x = int(raw_input('Enter an integer: '))
result = find(x)
if result is None:
print 'No combinations within parameters exist'
else:
root, pwr = result
print root, "**", pwr, "=", x
I'm not sure that's what you do want, though. ^ in Python is bitwise exclusive-or, not exponentiation. So it's peculiar that the problem statement used ^.
Another peculiarity is that "No combinations ..." will never be printed, because no matter what you enter for x, pow(x, 1) == x will be found as a solution.