Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Log(2 ** 62,2).is_integer() is returning false . Any ideas why?

i am trying to print

>>> math.log(2 ** 62,2).is_integer()

which returns

False

Similarly,

>>> math.log(2**62,2).is_integer()
False
>>> math.log(2**26,2).is_integer()
True
>>> math.log(2**28,2).is_integer()
True
>>> math.log(2**31,2).is_integer()
False
>>> math.log(2**32,2).is_integer()
True
>>> math.log(2**33,2).is_integer()
True
>>> math.log(2**31,2).is_integer()
False
>>> math.log(2**30,2).is_integer()
True
>>> math.log(2**63,2).is_integer()
True
>>> math.log(2**64,2).is_integer()
True
>>> math.log(2**62,2).is_integer()
False

The results are very vague, varying differently for various integers.

Any ideas why?

EDIT

Sylvain mentioned here that

>>> math.log(2**62,2) 

returns

62.00000000000001

why is that so? Please if anyone could explain this?

FYI -> for many numbers in range(100) it does returns proper integers as shown below

>>> for i in range(100):
        print 'math.log(2**'+str(i)+',2)' + ' --> ' + str(float(math.log(2**i,2))) + ' Is Integer? --> ' + str(math.log(2**i,2).is_integer())

math.log(2**0,2) --> 0.0 Is Integer? --> True
math.log(2**1,2) --> 1.0 Is Integer? --> True
math.log(2**2,2) --> 2.0 Is Integer? --> True
math.log(2**3,2) --> 3.0 Is Integer? --> True
math.log(2**4,2) --> 4.0 Is Integer? --> True
math.log(2**5,2) --> 5.0 Is Integer? --> True
math.log(2**6,2) --> 6.0 Is Integer? --> True
math.log(2**7,2) --> 7.0 Is Integer? --> True
math.log(2**8,2) --> 8.0 Is Integer? --> True
math.log(2**9,2) --> 9.0 Is Integer? --> True
math.log(2**10,2) --> 10.0 Is Integer? --> True
math.log(2**11,2) --> 11.0 Is Integer? --> True
math.log(2**12,2) --> 12.0 Is Integer? --> True
math.log(2**13,2) --> 13.0 Is Integer? --> True
math.log(2**14,2) --> 14.0 Is Integer? --> True
math.log(2**15,2) --> 15.0 Is Integer? --> True
math.log(2**16,2) --> 16.0 Is Integer? --> True
math.log(2**17,2) --> 17.0 Is Integer? --> True
math.log(2**18,2) --> 18.0 Is Integer? --> True
math.log(2**19,2) --> 19.0 Is Integer? --> True
math.log(2**20,2) --> 20.0 Is Integer? --> True
math.log(2**21,2) --> 21.0 Is Integer? --> True
math.log(2**22,2) --> 22.0 Is Integer? --> True
math.log(2**23,2) --> 23.0 Is Integer? --> True
math.log(2**24,2) --> 24.0 Is Integer? --> True
math.log(2**25,2) --> 25.0 Is Integer? --> True
math.log(2**26,2) --> 26.0 Is Integer? --> True
math.log(2**27,2) --> 27.0 Is Integer? --> True
math.log(2**28,2) --> 28.0 Is Integer? --> True
math.log(2**29,2) --> 29.0 Is Integer? --> False
math.log(2**30,2) --> 30.0 Is Integer? --> True
math.log(2**31,2) --> 31.0 Is Integer? --> False
math.log(2**32,2) --> 32.0 Is Integer? --> True
math.log(2**33,2) --> 33.0 Is Integer? --> True
math.log(2**34,2) --> 34.0 Is Integer? --> True
math.log(2**35,2) --> 35.0 Is Integer? --> True
math.log(2**36,2) --> 36.0 Is Integer? --> True
math.log(2**37,2) --> 37.0 Is Integer? --> True
math.log(2**38,2) --> 38.0 Is Integer? --> True
math.log(2**39,2) --> 39.0 Is Integer? --> False
math.log(2**40,2) --> 40.0 Is Integer? --> True
math.log(2**41,2) --> 41.0 Is Integer? --> True
math.log(2**42,2) --> 42.0 Is Integer? --> True
math.log(2**43,2) --> 43.0 Is Integer? --> True
math.log(2**44,2) --> 44.0 Is Integer? --> True
math.log(2**45,2) --> 45.0 Is Integer? --> True
math.log(2**46,2) --> 46.0 Is Integer? --> True
math.log(2**47,2) --> 47.0 Is Integer? --> False
math.log(2**48,2) --> 48.0 Is Integer? --> True
math.log(2**49,2) --> 49.0 Is Integer? --> True
math.log(2**50,2) --> 50.0 Is Integer? --> True
math.log(2**51,2) --> 51.0 Is Integer? --> False
math.log(2**52,2) --> 52.0 Is Integer? --> True
math.log(2**53,2) --> 53.0 Is Integer? --> True
math.log(2**54,2) --> 54.0 Is Integer? --> True
math.log(2**55,2) --> 55.0 Is Integer? --> False
math.log(2**56,2) --> 56.0 Is Integer? --> True
math.log(2**57,2) --> 57.0 Is Integer? --> True
math.log(2**58,2) --> 58.0 Is Integer? --> False
math.log(2**59,2) --> 59.0 Is Integer? --> False
math.log(2**60,2) --> 60.0 Is Integer? --> True
math.log(2**61,2) --> 61.0 Is Integer? --> True
math.log(2**62,2) --> 62.0 Is Integer? --> False
math.log(2**63,2) --> 63.0 Is Integer? --> True
math.log(2**64,2) --> 64.0 Is Integer? --> True
math.log(2**65,2) --> 65.0 Is Integer? --> True
math.log(2**66,2) --> 66.0 Is Integer? --> True
math.log(2**67,2) --> 67.0 Is Integer? --> True
math.log(2**68,2) --> 68.0 Is Integer? --> True
math.log(2**69,2) --> 69.0 Is Integer? --> True
math.log(2**70,2) --> 70.0 Is Integer? --> True
math.log(2**71,2) --> 71.0 Is Integer? --> True
math.log(2**72,2) --> 72.0 Is Integer? --> True
math.log(2**73,2) --> 73.0 Is Integer? --> True
math.log(2**74,2) --> 74.0 Is Integer? --> True
math.log(2**75,2) --> 75.0 Is Integer? --> True
math.log(2**76,2) --> 76.0 Is Integer? --> True
math.log(2**77,2) --> 77.0 Is Integer? --> True
math.log(2**78,2) --> 78.0 Is Integer? --> False
math.log(2**79,2) --> 79.0 Is Integer? --> True
math.log(2**80,2) --> 80.0 Is Integer? --> True
math.log(2**81,2) --> 81.0 Is Integer? --> True
math.log(2**82,2) --> 82.0 Is Integer? --> True
math.log(2**83,2) --> 83.0 Is Integer? --> True
math.log(2**84,2) --> 84.0 Is Integer? --> True
math.log(2**85,2) --> 85.0 Is Integer? --> True
math.log(2**86,2) --> 86.0 Is Integer? --> True
math.log(2**87,2) --> 87.0 Is Integer? --> True
math.log(2**88,2) --> 88.0 Is Integer? --> True
math.log(2**89,2) --> 89.0 Is Integer? --> True
math.log(2**90,2) --> 90.0 Is Integer? --> True
math.log(2**91,2) --> 91.0 Is Integer? --> True
math.log(2**92,2) --> 92.0 Is Integer? --> True
math.log(2**93,2) --> 93.0 Is Integer? --> False
math.log(2**94,2) --> 94.0 Is Integer? --> False
math.log(2**95,2) --> 95.0 Is Integer? --> False
math.log(2**96,2) --> 96.0 Is Integer? --> True
math.log(2**97,2) --> 97.0 Is Integer? --> True
math.log(2**98,2) --> 98.0 Is Integer? --> True
math.log(2**99,2) --> 99.0 Is Integer? --> True
like image 778
Prashant Shrivastava Avatar asked Mar 19 '23 16:03

Prashant Shrivastava


2 Answers

All results are floats. is_integer does not check if the type of the result is integer. It checks if the floating value is an integer.

Rounding errors might made is_integer not reliable though:

>>> math.log(2**26,2)
26.0
>>> math.log(2**62,2)
62.00000000000001

As the above operation are performed through the use of the natural logarithm, I guess the rounding error here is introduced by the division by log(2)
(as math.log(x,2) is math.log(x)/math.log(2)).

like image 134
Sylvain Leroux Avatar answered Mar 31 '23 12:03

Sylvain Leroux


For numbers above 2**53 the explanation is that double precision (64-bit) floating point numbers cannot represent integers bigger than that exactly. The logarithm function in these cases is already receiving an approximate input and of course it cannot provide exact output.

EDIT: powers of two can be represented exactly... the problem is for integers that are NOT a power of two and bigger than 2**53.

That log fails doing an exact computation for 2**31 is indeed somewhat surprising given that apparently most common hardware for PC today has instructions for computing logarithms in base 2 in the floating point unit.

Python code is however written in C and the C library doesn't provide a logarithm in base 2 library function in all build environments Python supports. This means that all computations are done passing from natural logarithm and a change of base; this explains inaccuracies even with small values like 2**31. For the generic math.log function there's no special handling for the case base is 2 even if the compiler provides support for it.

Python 3 math module contains however a log2 function and the code for computing the logarithm in base 2 uses a log2 primitive if this is present on the platform. Indeed in Linux math.log2(2**31) is exact, while math.log(2**31, 2) is not. I've read somewhere that Microsoft C++ math library doesn't implement log2 and thus I don't expect it to be exact in Python 3 implementation running in Windows (Python code is compiled with Visual C++).

EDIT: seems this is not true any more or was never true. math.log2 is accurate even on Windows builds of Python 3.

like image 34
6502 Avatar answered Mar 31 '23 12:03

6502