开发者

Ordering of evaluation using boolean or

开发者 https://www.devze.com 2023-01-12 10:52 出处:网络
So I\'ve got this snippet of code. And it works (It says 1 is non-prime).: n = 1 s = \'prime\' for i in range(2, n / 2 + 1):

So I've got this snippet of code. And it works (It says 1 is non-prime).:

n = 1
s = 'prime'
for i in range(2, n / 2 + 1):
    if n == 1 or n % i == 0:
        s= 'non-' +s
        break

print s

My problem is that if I change the fourth line to: if n % i == 0 or n == 1:, it doesn't work (it says 1 is prime.)

Why is that? Since I'm using or should it be that either one of t开发者_如何学Chem is True so the order doesn't count?

(I'm still learning about boolean so I may be making some basic mistake.)

Thanks in advance!

EDIT: Thanks for the answers; I never realized my issue with the range() function. And about the code working and not working: I have no idea what happened. I may have made some mistake somewhere along the way (maybe forgot to save before running the script. Although I could've sworn that it worked differently :P ). Maybe I'm just getting tired...

Thanks for the answers anyways!


In both cases, the body of the loop does not run, because when 'n' is 1, it does not fall within the range of (n,n/2+1)

The code you posted says that 1 is prime (again, because the loop body does not execute at all)


The precedence is fine. % is evaluated first, then ==, then or, so it breaks down into:

     ___or___
    /        \
  ==          ==
 /  \        /  \
n    1      %    0
           / \
          n   i

Your problem is that your for loop is not being executed at all, so that s is still set to "prime".

The range 2,n/2+1 when n is 1 equates to 2,1 which will result in the body not being executed.

In fact it won't be executed where n is 2 either since 2/2+1 is 2 and the range 2,2 doesn't execute. The values are the start and terminating value, not start and end (last) value - it's just fortuitous there that 2 is considered a prime by virtue of the initialisation of s :-)

Try this instead:

#!usr/bin/python

n = 9
s = 'prime'
if n == 1:
    s = 'non-prime'
else:
    i = 2
    while i * i <= n:
        if n % i == 0:
            s= 'non-prime'
            break
        i = i + 1
print s

It's wasteful going all the way up to n/2, the square root of n is all that's needed.


i think the problem is when n is 1, the loop is skipped.


Other answers already correctly addressed your specific problem (which, in other words, is that the loop executes only if n/2 + 1 > 2, that is, n/2 > 1, which means n > 2 with new-style division [[python 3 or suitable imports from the future or flags...]], n > 3 with classic style truncating division).

Wrt the specific question you posed:

Since I'm using or should it be that either one of them is True so the order doesn't count?

The order does count because or (like and) is a short-circuiting operator: specifically, or is guaranteed to go left to right, and stop if the left operand is true (because it does not need to know about the right one). This doesn't matter for your specific code, but it's crucial in cases such as, e.g.:

if i == 0 or n / i > 3: ...

If or wasn't going left-to-right (and stopping ASAP), the right-hand operand might get executed even when i equals 0 -- but then the division would raise an exception! With Python's rules, this code snippet won't raise exceptions (if i is an int, at least;-).

Again: this has nothing to do with the specific problem you're having (see other answers and the start of this one), but it's important for you to know for the future, so, since you asked, I took the opportunity to explain!-)


for n in range(101):
    s = 'prime'
    if n < 2 or not (n & 1): ## not(n & 1) == is even number (last bit 0) == not (n % 2) 
        s = 'non-'+s
    else:
        for i in range(3, int(n**0.5) + 1,2):
             if not(n % i):
                 s= 'non-' +s
                 break
    print "%i is %s" % (n,s)

You need not check all even numbers and you can stop the check at square root of n.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号