4

I was trying to write a simple program to determine if input integer is a power of two.

I had following code. It will fail the test case for n=536870912 (536870912 is the 2^29).

I tried with formating the number, format(y,'12g') the output is close to 0 but not equal to 0, 3.43965 e-07.

How should I overcome this number issue?

    s= math.log(n,2)
    [sh,y]=divmod(s,1)

    if y!=0:
    #if format(yu,'20f')!=format(0,'20f') :
        return False
    else:
        return True
Jivan
  • 21,522
  • 15
  • 80
  • 131
Alex
  • 41
  • 2

3 Answers3

3

If you want to compare floats and allow for a little floating-point inaccuracy, you would normally check if they are within a certain allowable distance of each other (if abs(x-y) < epsilon).

However, if you want to find out if an integer is a power of 2, you can do it like this:

def ispoweroftwo(n):
    return (n>0 and (n&-n)==n)

This works according to the rules of two's complement representation of signed numbers.

>>> ispoweroftwo(536870911)
False
>>> ispoweroftwo(536870912)
True
khelwood
  • 55,782
  • 14
  • 81
  • 108
2

The way to go about comparing floating point numbers for equality is abs(a - b) < tolerance, where tolerance = 1e-6 or some similar small number. In your case it would just be abs(y) < 1e-6.

For more info check out Accuracy here or a popular SO question.

Community
  • 1
  • 1
Horia Coman
  • 8,681
  • 2
  • 23
  • 25
1

If you need accuracy and you don't want to reinvent the accuracy-wheel yourself, you could have a look at NumPy, which is precisely designed for this kind of purpose (accurately making complex mathematical operations on big numbers of any kind).

import numpy as np

x = np.array([0, 1, 2, 2**4, 536870912])
np.log2(x)

# array([-Inf,   0.,   1.,   4., 29.])

See documentation for np.log2() or a quickstart tutorial.

Jivan
  • 21,522
  • 15
  • 80
  • 131