There are algorithms that depend on the number of bits per digit be divisible by 5.
Also, the marshal
format uses 15-bit digits. It is easy and efficient to split 30-bit digit on 15-bit digits.
There are algorithms that depend on the number of bits per digit be divisible by 5.
Also, the marshal
format uses 15-bit digits. It is easy and efficient to split 30-bit digit on 15-bit digits.
Which algorithms? And should that maybe be mentioned in longintrepr.h (which mentions marshal and a few other things)?
Just noting that gmpy2
(the popular Python wrapper for the GMP library) already supports len()
for its integer type:
>>> import gmpy2
>>> for i in range(17):
... print(i, len(gmpy2.mpz(i)))
0 1
1 1
2 2
3 2
4 3
5 3
6 3
7 3
8 4
9 4
10 4
11 4
12 4
13 4
14 4
15 4
16 5
So itâs the bit length. Although unlike the .bit_length()
method, len()
returns f for 0 instead of .bit_length()
's 0 result:
>>> z = gmpy2.mpz(0)
>>> len(z), z.bit_length()
(1, 0)
gmpy2 also happens to have an âmpz.num_digitsâ function (with default decimal base)
>>> import gmpy2
>>> gmpy2.mpz(0xFFFF).num_digits()
5
>>> gmpy2.mpz(0xFFFF).num_digits(16)
4
I would imagine this to be faster, though less readable:
import math
print(int(math.log10(abs(int(n)))) + 1)
If you read a few more messages, you get shown that this can have wrong results, platform dependent: Add int.__length__ method - #11 by mdickinson
Potentially only your larger formula is wrong and one would have to think that through, so I prefer to say that math.log10(10**15) == math.log10(10**15 - 1)
, which shows that log10
itself already canât distinguish these two numbers which have different lengths.
To avoid the floating-point imprecision of math.log10
and the sign inconsistency of str
one can use decimal.Decimal
instead:
import math
from decimal import Decimal
n = 10 ** 15 - 1
print(1 + math.floor(math.log10(n))) # outputs 16
print(len(str(n))) # outputs 15
print(len(Decimal(n).as_tuple().digits)) # outputs 15