Prime number checker function is faulty - python

I wrote a function to calculate whether or not a number is prime, but try as it might, it just seems unable to give the correct response. It also prints the n value that is being incremented. Here is the code for the function (in Python, by the way):
def isPrime(x):
for n in range(1, x):
print n
if x % n == 0:
return False
return True
If I input
isPrime(17)
the function returns
1
False
What is going wrong here?

Every number is divisible by 1 and itself. A prime number is a natural number that has no positive divisors other than 1 and itself. Therefore, if you start your for-loop with 1, every number x will pass the condition x % 1 == 0 in the first iteration, returning False.
To fix it, you need to start your loop with 2 instead of 1. Also, as a side-note, you just need to loop from 2 to sqrt(x), since if there exists a number q > sqrt(x) that divides x, then there must also be a number p = x / q which also divides x, and p < sqrt(x).

Related

Creating a function that checks perfect numbers python

I've been trying to create a function that checks for perfect numbers, I've used many of the resources I found here, but they don't seem to work for some reason. In my assignment, I'm required to find different types of numbers in a given range input, but this is the only function that doesn't work properly. This is what I have:
def is_perfect(a): #creates a perfect number checker
sum=0
for i in range(1,a):
if a%1==0:
sum += i
if sum==a:
return True
else:
return False
Change the line from a%1==0 to a%i==0 and your code will work perfectly. Because you've to check that the number is divisible from 1 to a and not only 1. It will return always True until it is not integer. Hence, it will keep adding all nos from 1 to a
A perfect number is any number that has the sum of it's devisors, excluding itself, equal to this number. Like the number six that is divided by 1, 2 and 3 and 1 + 2 + 3 = 6.
def is_perfect(number):
sum_ = sum([x for x in range(1, number) if number % x == 0])
return sum_ == number
is_perfect(6) # Returns True
is_perfect(10) # Returns False
is_perfect(28) # Returns True
I called the variable that sum all the divisors with a underscore because sum is already a function keyword in Python
def isPerfect( n ):
sum = 1
i = 2
while i * i <= n:
if n % i == 0:
sum = sum + i + n/i
i += 1
# If sum of divisors is equal to
# n, then n is a perfect number
return (True if sum == n and n!=1 else False)

Checking integers in python

I need to write a code that asks the user for a range of integers and then calculates which integers in that range have at least 3 factors (excluding 1 and the integer itself). I don't know how to take into consideration the fact that an integer can have multiple same factors, for example, in my code integer 8 returns a false value because the program divides it into two integers, 2 and 4. I want the return value to be true, because 8 can be divided into three factors of 2. How do i fix it?
def does_integer_have_3_or_more_factors(x):
num_of_factors = 0
for i in range(2, x):
if x % i == 0:
num_of_factors += 1
if num_of_factors >= 3 :
return True
else :
return False
def main():
integer1 = int(input("Give first positive integer.\n"))
integer2 = int(input("Give last integer.\n"))
print("These integers have at least 3 factors.")
for x in range(integer1, integer2 + 1):
if does_integer_have_3_or_more_factors(x) == True:
print(x)
main()
You need to use the factors you found, and apply them as often as necessary. Maybe you also want to keep track of the factors you found.
factors = []
...
for ... # see below
while x > 1 and not x%i:
factors.append(i)
x /= i
You can also stop checking for factors after sqrt(x) has been reached.
from math import sqrt
for i in range(2,int(sqrt(x))+1):
Finally, you're handling booleans in an overly complicated way. Just do
return len(factors) > 2 # "len(factors) > 2" will result in True or False directly
and check for
if does_integer_have_3_or_more_factors(x):
print(x)

Anyway to inverse factorial function?

So the question comes like this, I'm new to python:
def factorial_cap(num): For positive integer n, the factorial of n (denoted as n!), is the product
of all positive integers from 1 to n inclusive. Implement the function that returns the smallest
positive n such that n! is greater than or equal to argument num.
o Assumption: num will always be a positive integer.
# Examples
# factorial_cap(20) output is 4 since 3!<20 but 4!>20
# factorial_cap(24) output is 4 since 4!=24
# factorial_cap(1) output is 1 since 1!=1
# And here is what I got
def factorial_cap(num):
n = 1
for i in range (1,num+1):
n = n*i
I'm pretty sure this is the right function for factorial def. But I just couldn't figure out, instead of getting the 'total value', how can I just get the right output as I posted example above?
Btw, should I use 'return' at the end of def, or it does not matter in this case?
There needs to be a test for when the current total is greater than or equal to the requested number. So you can use the condition of a while loop to perform that check, and increment a counter, i, that keeps track of the current iteration. Then it's a matter of returning the current value of i that produced the value >= the required number:
def factorial_cap(num):
n = 1
i = 1
while n < num:
i += 1
n *= i
return i
>>> factorial_cap(20)
4
>>> factorial_cap(24)
4
>>> factorial_cap(25)
5
>>> factorial_cap(1)
1
>>> factorial_cap(3628800)
10
You want a return but that isn't n, but i
def factorial_cap(num):
n = 1
i = 0
while True:
i += 1
n = n*i
if n >= num:
break
return i
print(factorial_cap(20))
print(factorial_cap(24))
print(factorial_cap(1))

given and integer, return the next integer that is a prime number and a palindrome . Python

Given any random integer, create a function to find the next number that is a prime number and also a palindrome.
My attempt
def golf(number):
x = number + 1
for i in range(2, x):
if x % i == 0 or str(x) != str(x)[::-1]:
golf(number + 1)
return x
E.g golf(13) = 101
I'm actually looking for an alternative option than the recursion method i used. How can this best be accomplished without using recursion?
Thanks
Here's a variation on byron he's answer which adds several optimizations:
We can eliminate all even x values (other than 2) before doing any elaborate tests, since we can trivially tell they are not prime.
A small improvement is to only call str(x) once, and reuse the value later.
We can take advantage of the fact that all even-length palindromes are multiples of 11, which means that (except for 11 itself) they're not prime. We can jump ahead to the next odd-length x value.
Since we've already eliminated even numbers, our prime test only needs to test odd divisors. Further we can stop our loop when we reach sqrt(x), rather than going all the way to x itself.
Finally, there's no need to use a Boolean flag variable to carry the primeness out of the loop. If we don't break, the else block attached to the loop will be run.
The code:
import math
def next_prime_palindrome(x):
while True:
x += 1
if x > 2 and x % 2 == 0: # even numbers greater than 2 are non-prime
continue
s = str(x) # compute str(x) just once
if x > 11 and len(s) % 2 == 0: # all even-length palindromes are multiples of 11
x = 10 ** len(s) # so jump to the next odd-length integer
continue
if s != s[::-1]: # palindrome test
continue
for i in xrange(3, round(math.sqrt(x))+1, 2): # loop over odd potential divisors
if x % i == 0: # prime test
break
else: # this else block runs only if no break happened in the loop, so x is prime
return x
Here are some tests runs, showing a few cases where the optimizations save significant time:
>>> next_prime_palindrome(1)
2
>>> next_prime_palindrome(3)
5
>>> next_prime_palindrome(9)
11
>>> next_prime_palindrome(11)
101
>>> next_prime_palindrome(99999)
1003001
>>> next_prime_palindrome(999999999)
10000500001
A further improvement might be to directly generate palindromes, rather than working with integers to start with, and doing a palindrome test to filter them. That would get quite a bit further from your original design, so I'll leave that for someone else.
Palindrome are a sparser set of numbers than primes, and you can generate palindromes directly.
Consider the sequence 98.102
These are palidrome numbers you can base on these
989, 9889, 999, 9999, 10001, 100001, 10101, 101101, 10201, 102201
ADDED
Not also that all of the palidromes with an odd number of digits will come before the palidromes with an even number of digits.
If you write this as a generator (ie using yield) get get a straightforward algorithm for generating palindromic numbers in order.
For 1..9 you generate either 9 or 18 palindromes depending upon whether you consider 1 digit numbers palindromic.
For 10..99 you generate 90 even digit and 90 odd digit palindromes.
For 100..999 you generate 900 even digit and 900 odd digit palindromes.
You have just generated all 1989 (or 1997 if including single digit numbers) of the palindromic numbers less than 1 million. There are 78,498 primes less than 1 million
Any algorithm that is based on generating primes then testing for a palindrome will be much slower that generating palindromes and then testing for primes
def golf(number):
primes = []
i = 2
while i <= number:
if isPrime(i, primes):
primes.append(i)
i += 1
answer = primes[-1] + 1
while True:
if isPrime(answer, primes):
primes.append(answer)
if str(answer) == str(answer)[::-1]:
return answer
answer += 1
def isPrime(n, primes):
for (p for p in primes if p<=n**0.5):
if n%p == 0:
return False
return True
Your solution can be slightly modified in order to create an iterative solution:
def golf(number):
x = number + 1
while True:
is_golf = True
for i in range(2, x):
if x % i == 0 or str(x) != str(x)[::-1]:
is_golf = False
break
if is_golf:
return x
x += 1
improved according to Blckknght's advice, thanks.
def golf(number):
x = number
while True:
x += 1
if str(x) != str(x)[::-1]:
continue
for i in xrange(2, x):
if x % i == 0 :
break
else:
return x

What is wrong with my primes number program?

def is_divisible(n, primes):
for i in range(1, len(primes)):
if n % primes[i] == 0:
return True
return False
primes = []
def find_primes(N):
for j in range(1, N):
if is_divisible(j, primes) == False:
primes.append(j)
return primes
print(find_primes(200))
It should tell if a number is prime. And just prints 1.
I think your issue is the indentation of the return statement. Here's your code fixed up:
def is_divisible(n, primes):
for i in range(0, len(primes)):
if n % primes[i] == 0:
return True
return False
def find_primes(N):
primes = []
for j in range(2, N):
if is_divisible(j, primes) == False:
primes.append(j)
return primes
Also avoid globals if you don't have to. find_primes doesnt need to access a global primes list it can declare it locally. Also, notice the range in find_primes that starts at 2 since every number is divisible by 1. Also, indendation matters. In both functions you do not iterate over the entire loop before returning the output (in find_primes) or the default (in is_divisible)
All numbers are divisible by 1. When your program checks if 1 is a prime it determines yes it is so it appends it to the array. Then, when it checks if the next number 2 is divisible by any of the existing primes it says yes, it is divisible by 1 therefore it is not a prime etc etc.
The first number you add is 1, every number is divisible by one and therefore is_divisible(x,1)== True and no number other then 1 is appended to the primes list.
In addition to the remark above (your program should start from 2), you do not want to return until you've completed the 'for j in range((2),N): ' loop. That is, you need to dedent the 'return primes' statement.
Your return primes line is inside the for loop, which means that it just check the first number (i.e. 1), and returns the result of that single calculation.
Your program should instead return the primes after looking at all the number, not just at the first one.

Categories

Resources