Sparrow
Sparrow

Reputation: 305

Weird output on converting code from C to Python

I could successfully rum a simple program to check whether the number is prime or not in C. The code looks like this

void isPrime(int n)
{
    int a=0,i;
    for(i=1;i<=n;i++)
    {
    if(n%i==0)
    a++;
    }
    if(a==2)
    {
        printf("\n%d is prime",n);
    }
    else
    {
        printf("\n%d is not prime",n);
    }
}

int _tmain(int argc, _TCHAR* argv[])
{


 for(int i=2;i<=20;i++)
 {
     isPrime(i);
 }

    return 0;
}

The above code runs perfectly when I compile. I am a beginner in python and I have converted the same code into python, which looks like this.

def isPrime(n):
    a=0
    for x in range(1,n):
        if n%x==0:
            a=a+1   
    if a==2:
        print("{} is prime".format(n))
    else:
        print("{} is not prime".format(n))

for n in range(2,20):
    isPrime(n)

But I get a wrong output in python. The output is somewhat weird which says

2 is not prime
3 is not prime
4 is prime
5 is not prime
6 is not prime
7 is not prime
8 is not prime
9 is prime
10 is not prime
11 is not prime
12 is not prime
13 is not prime
14 is not prime
15 is not prime
16 is not prime
17 is not prime
18 is not prime
19 is not prime

I have found out that the count of 'a' is 1 less than the actual count required. For example, in case of n=8, a should be 4. But its getting counted as 3. What could be the reason?

Upvotes: 1

Views: 76

Answers (3)

user2489252
user2489252

Reputation:

I think the problem was with your range as mentioned above. Can I give you some short tips to make your code more "Pythonic"? :)

Instead of
if n%x==0
you would simply write
if not n%x

and instead of a=a+1 you could use the in-place operator, e.g., a += 1 Here, it wouldn't make much of a difference, but if you are working with mutable objects (due to the __iadd__ method, I have more details here) you would gain a significant performance increase, e.g.,

def slow(a):
    for i in range(1000):
        a = a + [1,2]

def fast(a):
    for i in range(1000):
        a += [1,2]

a = []
b = []
%timeit -r 3 -n 1000 slow(a)
%timeit -r 3 -n 1000 fast(b)


1000 loops, best of 3: 2.94 ms per loop
1000 loops, best of 3: 181 µs per loop

Same for the binary operator instead of the format() method, however, I like the latter one better (due to its more powerful minilanguange and I would recommend it if you don't care about speed in certain computations)

%timeit -r 3 -n 1000 '{} World'.format('Hello')
%timeit -r 3 -n 1000 '%s World' %('Hello')

1000 loops, best of 3: 472 ns per loop
1000 loops, best of 3: 27.3 ns per loop


def isPrime(n):
    a = 0
    for x in range(1, n+1):
        if not n%x:
            a += 1   
    if a==2:
        print("{} is prime".format(n))
    else:
        print("{} is not prime".format(n))

for n in range(2, 20):
    isPrime(n)

Upvotes: 1

mdml
mdml

Reputation: 22882

The issue you have is that the last value produced range(start, stop) is stop-1; see the docs. Thus, isPrime should have the following for loop:

for x in range(1, n+1):

This will faithfully replicate the C code, and produce the correct output. (Note that this is also why you are only checking the numbers [2, 19] for whether they're prime, as opposed to [2, 20].)

Upvotes: 2

timgeb
timgeb

Reputation: 78700

Why don't you add some print statements so you can see where the code fails? Adding some prints should be your first reflex when debugging.

def isPrime(n):
    a=0
    for x in range(1,n):
        print('x,a', x,a)
        if n%x==0:
            print('incrementing a...')
            a=a+1
    print('a after loop:', a)
    if a==2:
        print("{} is prime".format(n))
    else:
        print("{} is not prime".format(n))

Output for isPrime(2):

x,a 1 0
incrementing a...
a after loop: 1
2 is not prime

Output for isPrime(7):

x,a 1 0
incrementing a...
x,a 2 1
x,a 3 1
x,a 4 1
x,a 5 1
x,a 6 1
a after loop: 1
7 is not prime

As you can see, a is never 2 because the n%n test is never executed, because with x in range(1,n), the last value for x is n-1. However, if you change your range to range(1,n+1), the test will be made:

x,a 1 0
incrementing a...
x,a 2 1
x,a 3 1
x,a 4 1
x,a 5 1
x,a 6 1
x,a 7 1
incrementing a...
a after loop: 2
7 is prime

Upvotes: 4

Related Questions