1

I was working with numbers up to 2100000. I am stuck at this point. Some of the numbers are not giving correct result as in the title:

>>> math.log(2**5910, 2)
5909.99999999999
>>> math.log(2**5910-1,2)
5909.99999999999
>>> math.log(2**5910+1,2)
5909.99999999999

How can i differentiate between log2(2^5910-1), log2(2^5910), log2(2^5910+1)? What I want is the characteristic of log2(n) to be exactly correct and I don't care about preciseness of mantissa. But it should give an integer in case of perfect power or atleast tell its a perfect power or not. Currently I am using this function:

def log(n):
    c=int.bit_length(n)-1
    m=0.5
    if(2**c==n):m=0
    return c,m
Mark Dickinson
  • 29,088
  • 9
  • 83
  • 120
HarshR
  • 75
  • 1
  • 9
  • Toby is right. If you want you can use: round(math.log(2**5910, 2)). – Stef van der Zon Nov 15 '18 at 14:17
  • But it will give same answers for many no.s eg. (2^5910)-1 and 2^5910 will have same answers after rounding. – HarshR Nov 15 '18 at 14:42
  • 1
    Floating point arithmetic is extremely fast: but the price to pay for that speed is precision. – Matt Messersmith Nov 15 '18 at 15:02
  • 1
    Your edit change the question significantly. If you want to work with numbers requiring this precision, you need an extended-precision floating-point package or some other extended-precision mathematics software. I have not used such packages for Python, so I cannot advise on them. However, you might consider describing more about what you are doing with numbers up to 2^100000, as there may be an alternative approach which people could advise about. – Eric Postpischil Nov 15 '18 at 16:38
  • If you're doing integer math, and simply want to know how many bits are in the binary representation of an integer, look into [`int.bit_length()`](https://docs.python.org/3/library/stdtypes.html#int.bit_length). Also note that in Python 3 there's a `math.log2` function, which (at least on my machine) gives `5910` exactly for your two inputs. But it sounds as though you want `.bit_length()` to me. – Mark Dickinson Nov 15 '18 at 17:47
  • You can get a very good approximation of the difference by using the Maclaurin series for `log(1+x) = x -x^2 + O(x^3)`. For every n you have: `log2(2^n)-log(2^n-1) = log2(2^n)-log(2^n(1-1/2^n)) = log2(1-1/2^n) = log(1-1/2^n) / log(2) = 1/(2^n*log(2))+...` So with n=5910 you get for the difference `1/(2^5910*log(2)) = 0.118*10^(-1178)` – gammatester Nov 15 '18 at 18:29
  • It will work if I could know that the no. is a perfect power of 2 or not. If it is not then which side of perfect power it lies. In the given case 2**5910+1 is also giving log as 5909.9999... but obviously it should be 5910.000... – HarshR Nov 16 '18 at 07:04
  • 1
    There's an easy test for powers of two: a positive integer `n` is a power of two if and only if `n & (n-1) == 0`. If you combine that with use of `bit_length`, you should be able to do what you need. – Mark Dickinson Nov 16 '18 at 07:58
  • Nominating this question for re-opening: the marked duplicate is not appropriate at this point (if it ever was). @Harhaaakr: it might help if you tell us what you're using this _for_. – Mark Dickinson Nov 16 '18 at 08:00
  • Thanks @MarkDickinson, – HarshR Nov 16 '18 at 08:30
  • I was tryin to do recursion as- `def f1(m): L=characteristic of log2(m) if m is a perfect square: return f2( L ) else: n1=m-(2^L) return f2(L) - f1(n1)` f2(x) is a simple function of x – HarshR Nov 16 '18 at 08:41

0 Answers0