So its just a simple prime factorization calculator
Im not sure why its infinitely looping. Im pretty new to python and not entirely sure on how the while loop works
def print_prime_factors(number):
x = 2
while x < number:
if number % x == 0:
y = number/x
print(str(x)+",")
y = number
if x > y:
break
x = x + 1
print_prime_factors(100)
# Should print 2,2,5,5
# DO NOT DELETE THIS COMMENT```
Your code has an indentation error.
This line:
x = x + 1
should be shifted over one indent. You're only incrementing x whenever it is a factor of the number, which means that the program will enter an infinite loop by repeatedly checking whether number is divisible by a non-factor of number.
after the first iteration x changes and the if statements is never true again, which makes x never changes again. Seens to be just indentation problem.
(1) The first bug is, as others have said, that your line x = x + 1 that increments candidate x should be unindented one level, so it's under the while-loop.
(2) But you also have a bug with what you're doing with quotient y, it's mystifying.
When you identify that x is a factor of number, just print x. You compute the quotient y = number/x, silently throw it away, then assign y = number, which again gets thrown away. You could have just directly tested if x > number: ... break.
but even that is roundabout. Your while-loop that starts x at 2, increments x by +1, and stops when x > number, is really just a for-loop in disguise: for x in range(2, number+1): ...
But you can show we strictly only need to do:
for x in range(2, ceil(sqrt(number)+1): ... where we use math.sqrt, math.ceil
...really you need to store the quotient between iterations, and when it gets to 1 you know you can terminate early; you've found all the divisors of number
Related
I have a general idea of what to do, but my code is a mess and I'm having some trouble writing the algorithm in python for
cos(x)=1-(x^2)/2!+(x^4)/4!-(x^6)/6!+...
where x is in radians, computing cos(x) after 20 terms using while loops. So far what I've written is
x = float(input("Enter a value for x in degrees."))
x = (x*3.14159)/180
num_of_terms = 0
num = 1.0 ##numerator
y = 1.0
cosx = 1.0
while num_of_terms<1:
num_of_terms+=1
cosx = (num/y)
while num_of_terms>=1 and num_of_terms<=20:
num_of_terms+=1
num = num*(x*x)
y = y*num_of_terms*(num_of_terms-1)
if num_of_terms%2==0:
cosx = cosx+(-num/y)
else:
cosx = cosx+(num/y)
print(cosx)
I don't know how close I even am to being correct (I know it's wrong in at least some places so I can't properly check using math.cos) but the main question I have is how to switch from positive --> negative each term. The assignment states that I cannot use exponentiation operators, and before I was trying to do something like
x = float(input("Enter a value for x in degrees."))
x = (x*3.14)/180
num_of_terms = 0
y = 0
z = 1
cosx = ((-1)**(z-1))*((x**z)/(y))
so that the sign would switch for every other term. Now I have (as you can see above)
if num_of_terms%2==0:
cosx = cosx+(-num/y)
else:
cosx = cosx+(num/y)
which is incorrect, or at least the output I'm getting is incorrect.
You can handle the sign quite simply:
sign = -1
while num_of_terms <= 20:
sign = -sign
...
cosx += sign * num/y
You also have a structure problem in your loops: the first loop will terminate after one iteration ... except you've properly prevented it from getting back there. This is poor use of a loop.
Just initialize your variables before the loop, and then proceed as expected. Since you know how many times to iterate, use a for instead of a while.
cosx = (num/y)
for num_of_terms in range(1, 21):
...
You will find other computational problems in your code. Print out values each time through the loop to help track your execution and computations. At the start, just go through 3 or 4 times instead of 20.
For the factorial, keep a running product: it's like a running sum, except that you initialize it at 1, and multiply each time through the loop.
Okay; stick with the while. Now, manage your loop index and computational index. If you're doing term #1, what should the exponent be? What numbers do you multiply into y? Now identify the same values for term #2 and term #3.
More directly, stick in a print statement to track num_of_terms, y, and cosx. When you're doing term #3, what is y? It should be 4! or 6! (depending on how you number your terms), but it's not. Where did you go wrong?
Your problem is in the computation of the factorial. You're multiplying by num_of_terms, which only increments by one each time through the loop - you need something that changes by 2 each time through the loop. At least you're correctly multiplying both that number and the number-1.
I need to write a program that prints the greatest common divisor of two entered integers, and also prove the correctness of it. I wrote the following:
def main():
x = int(input("Enter the first integer: "))
y = int(input("Enter the second integer: "))
print(gcd(x,y))
def gcd(x,y):
if x > y:
smaller = y
else:
smaller = x
for i in range(1, smaller + 1):
if ((x % i == 0) and (y % i == 0)):
gcd = i
return gcd
main()
The precondition is clearly that x and y should be two integers. The postcondition is the greatest common divisor of x and y. I need to identify the loop invariant, and show that it is ok after initialization, that it remains true after every iteration. Also, I'm suppose to prove the postcondition by using the loop invariant and show that the loop is finite.
I think the loop invariant is that i is always smaller or equal to x and y, and that x % i = r and y % i = s for some integers r and s. This clearly holds for every iteration. The loop continues until r = 0 and s = 0, and then it terminates. Finiteness is guaranteed because the iteration has an upper bound.
Is my reasoning correct here? Does this proves the correctness of the loop?
I think you can state a loop invariant a bit more clearly if you initialize the gcd variable to 1 before entering the loop (which be over a range starting at 2 if you want). Your invariant will be:
gcd is the largest integer less than or equal to i such that x % gcd == y % gcd == 0.
Your loop ends because i iterates over a finite range (ending with i == min(x, y)). The postcondition is that gcd is the greatest common divisor of x and y, which is proved by the loop invariant (as long as you can prove the GCD of two numbers is not larger than the smaller of them).
I'm writing a function that, given a random int, will return the next int that is both a prime number and a palindrome. i.e getint(13) will return 101.
One of the conditions of this function is that recursion is not allowed.
Where am i going wrong here?
def golf(number):
x = number +1
for i in range(2, x):
while str(x) != str(x)[::-1] and x % i == 0:
x += 1
return x
Divide the problem into smaller pieces. It will be easier for you to understand what's going on:
def golf(number):
x = number + 1
while True:
if is_palindrome(x) and is_prime(x):
return x
x += 1
Now all you have to do is implement is_palindrome(x) and is_prime(x):
import math
def is_prime(x):
for i in xrange(2, math.ceil(math.sqrt(x))+1):
if x % i == 0:
return False
return True
def is_palindrome(x):
x = str(x)
return x == x[::-1]
Side note: the math.ceil(math.sqrt(x))+1 might be an overkill (perhaps int(...)+1 is enough) if math.sqrt works correctly for squares (i.e. does not depend on floating point calculations so math.sqrt(a*a)==a is always true). Well in worst case the loop will do one more iteration then necessary. Better safe then sorry.
Your for loop will only go as far as x's initial value: the range(2,x) is computed only once, right after x = number + 1. So increasing x inside the loop doesn't make a difference. Consider using a while loop, something like:
i = 2
while i <= x:
...
i += 1
And you should probably first check is x is a palindrome (a "cheap" operation) and then, if it is, check weather it is prime (an "expensive" operation), not try do it all in a couple of nested loops that make little sense.
In your code:
def golf(number):
x = number +1
for i in range(2, x):
while str(x) != str(x)[::-1] and x % i == 0:
x += 1
return x
The program execution will not satisfy the while loop half of the time since any even number will not be divisible by any odd number and vice-versa. Also in a single iteration of the for loop, x will be incremented every time the while loop is satisfied.
You need to separate the prime checking and palindrome checking. The approach given by freakish is the simplest.
So, I read the pseudocode from http://www.javascripter.net/math/primes/miller_rabin_pseudocode.txt, and thought it would be cool to write it in python. So I wrote this:
n = input('Enter a number to test ')
n = int(n)
a=int(5)
d = n - 1
s = 0
while (d % 2 == 0):
s = s + 1
d = int(d/2)
x = a**d
x = x % n
if (x==1 or x==(n-1)):
print("probably prime")
r = int(1)
while(r<(s-1)):
x = x**2
x = x%n
if (x==1):
print ("composite")
if (x==(n-1)):
print ("probably prime")
print("if nothing above is printed n is composite")
It worked pretty well, but as soon as I got into six digit numbers it was incredibly slow. So I found some code of http://rosettacode.org/wiki/Miller-Rabin_primality_test#Python, and it was almost instant, even with large (10^30) numbers.
So, what did I do wrong int the above code that made it so much slower?
You should also replace:
x = a**d
x = x % n
With:
x = pow(a, d, n)
Which does modular exponentiation much faster than the naive method, as it takes modulus at each multiply, rather than building a ginormous number and taking modulus after.
The second loop in the linked code does only 5 iterations at maximum, whereas your does something like log(n).
EDIT:
Or even more - the "r" variable is never modified, so the loop's exit condition will never be satisfied. The only possibility to exit the loop are the breaks.
The calculation of the integer part of the square root of a number can be done by trial and error, starting from 1, by executing the square until the result is less than or equal to the starting value of which is calculated by the root.
The following program returns the integer part of the root
def radice(x):
z = 0
t = 0
while True:
t = z*z
if t > x:
z -= 1
return z
z += 1
radice(17) // 4
Will be possible to write it without using functions and break?
Here is my code witout function but I dont' know how to write the same algo with no break
z = 0
t = 0
while True:
t = z*z
if t > x:
z -= 1
break
z += 1
print 'The integer part of the root is: ', z
This should suffice:
>>> int(17**0.5)
4
17**0.5 generates the square root of 17, and int basically removes the decimals, leaving you with the "integer part of the root".
Without using any functions, and if you want an integer result, complex code (like your own) is needed. However, if a float will do, then you could try this:
>>> (17**0.5)//1
4.0
This essentially does the same as the int call, but will return a float if either side is a float.
As you said the integer part of the square root of a number can be done by trial and error, starting from 1, by executing the square until the result is less than or equal to the starting value of which is calculated by the root.
Said that you can write the code without using function and break statements; here is the code:
n = input("insert a number: ")
r = 1
while (r * r <= n):
r = r + 1
print "the result is:", r -1
Parens are for clarity, not required
>>> (17**.5)-(17**.5)%1
4.0
Ok, let's think logically.
You cannot use break, so the only way to get out of the while loop is to break its condition.
If it's True, it cannot be broken, so we have to think about the proper condition to stop iterating. And this condition is already used in your algorithm: you exit when t > x, or z * z > x. So the condition to continue iteration should be the opposite, i.e. z * z <= x. And we have this simple solution.
x = 17
z = 0
while z * z <= x:
z += 1
print 'The integer part of the root is: ', z - 1
As a general rule, try to shy away from those while True: loops. While they are sometimes useful, they're generally harder to read and understand, this is probably why your teacher limits the use of break. The function was prohibited probably because return is just another way of escaping the loop. But those are exceptional: the normal way to end a loop is to break its condition, so this is how it should be written.