简体   繁体   English

在 Python 中处理大数字并将它们写入文件

[英]Working with big numbers in Python and writing them to file

I'm trying to find an efficient way to do the following in Python:我正在尝试找到一种在 Python 中执行以下操作的有效方法:

   a = 12345678901234567890123456**12345678
   f = open('file', 'w')
   f.write(str(a))
   f.close()

The calculation of the power takes about 40 minutes while one thread is utilized.使用一个线程时,计算功率大约需要 40 分钟。 Is there a quick and easy way to spread this operation over multiple threads?是否有一种快速简便的方法可以将此操作分散到多个线程上?

As the number is quite huge, I think the string function isn't quite up to the task - it's been going for almost three hours now.由于数量很大,我认为字符串函数不能胜任这项任务——它已经持续了将近三个小时。 I need the number to end up in a text file.我需要以文本文件结尾的数字。 Any ideas on how to better accomplish this?关于如何更好地实现这一目标的任何想法?

I would like to give a lavish ;-) answer, but don't have the time now.我想给出一个丰富的 ;-) 答案,但现在没有时间。 Elaborating on my comment, the decimal module is what you really want here.详细说明我的评论, decimal模块是您在这里真正想要的。 It's much faster at computing the power, and very very much faster to convert the result to a decimal string:它的速度更快,在计算能力,而且非常非常更快的结果转换为十进制字符串:

>>> import decimal

You need to change its internals so that it avoids floating point, giving it more than enough internal digits to store the final result.您需要更改其内部结构以避免浮点数,从而为其提供足够多的内部数字来存储最终结果。 We want exact integer arithmetic here, not rounded floating-point.我们在这里需要精确的整数运算,而不是四舍五入的浮点数。 So we fiddle things so decimal uses as much precision as it's capable of using, and tell it to raise the "Inexact" exception if it ever loses information to rounding.所以我们摆弄一些东西,使decimal使用尽可能多的精度,并告诉它如果它丢失了四舍五入的信息,就引发“不精确”异常。 Note that you need a 64-bit version of Python for decimal to be capable of using enough precision to hold the exact result in your example:请注意,您需要 64 位版本的decimal Python 才能使用足够的精度来保存示例中的确切结果:

>>> import decimal
>>> c = decimal.getcontext()
>>> c.prec = decimal.MAX_PREC
>>> c.Emax = decimal.MAX_EMAX
>>> c.Emin = decimal.MIN_EMIN
>>> c.traps[decimal.Inexact] = 1

Now create a Decimal for the base:现在为基数创建一个Decimal

>>> base = decimal.Decimal(12345678901234567890123456)
>>> base
Decimal('12345678901234567890123456')

And raise to the power - the exponent will automatically be converted to Decimal , because the base is already Decimal :并提高幂 - 指数将自动转换为Decimal ,因为基数已经是Decimal

>>> x = base ** 12345678

That takes less than a minute on my box!在我的盒子上花费不到一分钟! The reasons for that are involved.其中的原因就涉及到了。 It's not really because it's working in base 10, but because the person who wrote the decimal module implemented "advanced" algorithms for doing very large multiplications.这并不是因为它以 10 为基数工作,而是因为编写decimal模块的人实施了“高级”算法来进行非常大的乘法运算。

Now convert to a string.现在转换为字符串。 Because it's already stored in a variant of base 10, converting to a decimal string goes very fast (a few seconds on my box, just because the string has hundreds of millions of digits):因为它已经存储在基数 10 的变体中,所以转换为十进制字符串的速度非常快(在我的盒子上几秒钟,只是因为字符串有数亿个数字):

>>> y = str(x)
>>> len(y)
309771765

And, for sanity, let's just look at the last 10, and first 10, digits:而且,为了理智,让我们看看最后 10 位和前 10 位数字:

>>> y[-10:]
'6044706816'
>>> y[:10]
'2759594879'

As @StefanPochmann noted in a comment, the last 10 digits can be obtained very quickly with native ints by using modular (3-argument) pow() :正如@StefanPochmann 在评论中指出的那样,可以通过使用模块化(3 个参数) pow()使用本机整数非常快速地获得最后 10 位数字:

>>> pow(int(base), 12345678, 10**10)
6044706816

Which matches the last 10 digits of the string above.它匹配上面字符串的最后 10 位数字。 For the first 10 digits, we can use decimal again but with much less precision, which will cause it (you'll just to have trust me on this) to use a different approach under the covers:对于前 10 位数字,我们可以再次使用decimal ,但精度要低得多,这将导致它(您只需相信我)在幕后使用不同的方法:

>>> c.prec = 12
>>> c.traps[decimal.Inexact] = 0  # don't trap on rounding!
>>> base ** 12345678
Decimal('2.75959487945E+309771764')

Rounding that back to 10 digits matches the earlier result, and the exponent is consistent with the length of y too.将其四舍五入为 10 位数字与先前的结果匹配,并且指数也与y的长度一致。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM