从Python long访问大数的最高位数

从Python long访问大数的最高位数,python,long-integer,bignum,Python,Long Integer,Bignum,我正在python中处理数万位数的数字。long类型在对这些数字进行数学运算时效果很好,但是我无法以足够快的方式访问这些数字的最高位数。请注意,我不知道这个数字包含多少位数。“最高位数”是指最高有效位的位数,最低位数可以使用模数快速访问 我可以想出两种在python中访问这些数字的方法,但它们对我来说都太慢了。我尝试过转换成字符串并通过数组方法访问数字,但是当您有10000多个数字时,类型转换会很慢。或者,我可以简单地屏蔽位并截断,但这需要我知道长度中有多少位。查找长字符串中的位数需要在计数器上

我正在python中处理数万位数的数字。long类型在对这些数字进行数学运算时效果很好,但是我无法以足够快的方式访问这些数字的最高位数。请注意,我不知道这个数字包含多少位数。“最高位数”是指最高有效位的位数,最低位数可以使用模数快速访问

我可以想出两种在python中访问这些数字的方法,但它们对我来说都太慢了。我尝试过转换成字符串并通过数组方法访问数字,但是当您有10000多个数字时,类型转换会很慢。或者,我可以简单地屏蔽位并截断,但这需要我知道长度中有多少位。查找长字符串中的位数需要在计数器上进行循环和掩码测试,这肯定比字符串转换慢

看起来long类型实际上包含一个bignum数组。是否有某种方法可以访问存储long的底层数据结构,或者可能检查long与基类型之间的位数


如果有人感兴趣,我可以提供一个基准测试示例。

一个简单的方法,无需深入研究long类型的低级实现:

>>> n = 17**987273 # 1.2 million digits number

>>> digits = int(math.log10(n))

>>> k = digits - 24 # i.e. first 24 digits

>>> n / (10 ** k)
9953043281569299242668853L
在我的机器上运行得很快。我试图得到这个数字的字符串表示形式,这需要花费大量的时间

对于Python3.x,使用
n//(10**k)

一些具有如此大数字的计时(速度快140倍):


Python2.7有一个关于整数的方法。

这里有一个非常难看的单行程序,它将提取前几个十进制数字:

(x >> (x.bit_length()-50))*(10**(math.fmod((x.bit_length()-50)*math.log(2)/math.log(10), 1)))
如果x的值约为10000位小数,则应得到精确到12位左右的答案。当x变大时,你的精确度会降低

如果你愿意使用外部模块,我会看看。gmpy2库提供对多精度整数和小数运算的GMP(或MPIR)库、多精度浮点运算的MPFR库和多精度复数运算的MPC库的访问。gmpy2整数比Python的原生long更快,您可以将长整数转换为浮点数,只提取前导数字。上述一个班轮只是变成:

gmpy2.mpfr(x).digits()[0]
即使数字越来越大,gmpy2方法仍将保持准确性


免责声明:我维护gmpy2。

如果您知道数量级,您可以除以
10**(orderMag-1)
。整数除法将为您提供最重要的数字位数未知。可能使用C访问它,有趣的线程您需要十进制数字还是只需要位?@AdamCadien:那么您不能使用
.bit\u length()
(Python 2.7+)要在不循环的情况下获得位数,然后右移向下?一个稍微修改的解决方案bignum/10**(int(math.log10(bignum))-ndig)。使用log10是个好主意,但我发现这只比str转换快一点,我仍然认为访问bignum数组会最快。@AdamCadien我的计时速度要快得多。我补充了答案。。。顺便说一句,访问bignum数据可能会使您的代码不可移植。我发现我的代码在其他地方效率低下,导致意外的速度减慢。log10解决方案非常有效!
gmpy2.mpfr(x).digits()[0]