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

在Python中处理大数字并将其写入文件,python,Python,我试图找到一种在Python中执行以下操作的有效方法: a = 12345678901234567890123456**12345678 f = open('file', 'w') f.write(str(a)) f.close() 当使用一个线程时,计算功耗大约需要40分钟。是否有一种快速简便的方法将此操作扩展到多个线程 由于这个数字相当大,我认为字符串函数不太适合这个任务——它已经运行了将近三个小时了。我需要一个文本文件中的数字。 关于如何更好地完成这一点,有什么想

我试图找到一种在Python中执行以下操作的有效方法:

   a = 12345678901234567890123456**12345678
   f = open('file', 'w')
   f.write(str(a))
   f.close()
当使用一个线程时,计算功耗大约需要40分钟。是否有一种快速简便的方法将此操作扩展到多个线程

由于这个数字相当大,我认为字符串函数不太适合这个任务——它已经运行了将近三个小时了。我需要一个文本文件中的数字。
关于如何更好地完成这一点,有什么想法吗?

我想给出一个慷慨的建议;-)回答,但是现在没有时间。详细说明我的评论,
decimal
模块正是您在这里真正想要的。它的计算能力要快得多,将结果转换为十进制字符串的速度要快得多:

>>> import decimal
您需要更改它的内部结构,以便它避免浮点运算,从而为它提供足够多的内部数字来存储最终结果。我们需要的是精确的整数运算,而不是四舍五入的浮点运算。所以我们把事情弄得乱七八糟,这样
decimal
就可以尽可能多地使用精度,并告诉它,如果由于舍入而丢失信息,就会引发“不精确”异常。请注意,对于
十进制
,您需要64位版本的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
现在为基础创建一个
十进制

>>> base = decimal.Decimal(12345678901234567890123456)
>>> base
Decimal('12345678901234567890123456')
并提高到幂次-指数将自动转换为
十进制
,因为基数已经是
十进制

>>> x = base ** 12345678
在我的箱子上不到一分钟!这其中的原因是多方面的。这并不是因为它在10进制下工作,而是因为编写
decimal
模块的人实现了“高级”算法来进行非常大的乘法运算

现在转换为字符串。因为它已经存储在10进制的变体中,所以转换为十进制字符串的速度非常快(在我的框中只需几秒钟,因为字符串有数亿位数):

为了理智起见,让我们看看最后10位和前10位数字:

>>> y[-10:]
'6044706816'
>>> y[:10]
'2759594879'
正如@StefanPochmann在一篇评论中所指出的,通过使用模块化(3参数)
pow()
,使用本机int可以非常快速地获得最后10位数字:

它与上面字符串的最后10位匹配。对于前10位数字,我们可以再次使用
十进制
,但精度要低得多,这将导致它(请相信我)在封面下使用不同的方法:

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

将其四舍五入到10位与前面的结果匹配,并且指数也与
y
的长度一致。

我想给出一个详细的解释;-)回答,但是现在没有时间。详细说明我的评论,
decimal
模块正是您在这里真正想要的。它的计算能力要快得多,将结果转换为十进制字符串的速度要快得多:

>>> import decimal
您需要更改它的内部结构,以便它避免浮点运算,从而为它提供足够多的内部数字来存储最终结果。我们需要的是精确的整数运算,而不是四舍五入的浮点运算。所以我们把事情弄得乱七八糟,这样
decimal
就可以尽可能多地使用精度,并告诉它,如果由于舍入而丢失信息,就会引发“不精确”异常。请注意,对于
十进制
,您需要64位版本的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
现在为基础创建一个
十进制

>>> base = decimal.Decimal(12345678901234567890123456)
>>> base
Decimal('12345678901234567890123456')
并提高到幂次-指数将自动转换为
十进制
,因为基数已经是
十进制

>>> x = base ** 12345678
在我的箱子上不到一分钟!这其中的原因是多方面的。这并不是因为它在10进制下工作,而是因为编写
decimal
模块的人实现了“高级”算法来进行非常大的乘法运算

现在转换为字符串。因为它已经存储在10进制的变体中,所以转换为十进制字符串的速度非常快(在我的框中只需几秒钟,因为字符串有数亿位数):

为了理智起见,让我们看看最后10位和前10位数字:

>>> y[-10:]
'6044706816'
>>> y[:10]
'2759594879'
正如@StefanPochmann在一篇评论中所指出的,通过使用模块化(3参数)
pow()
,使用本机int可以非常快速地获得最后10位数字:

它与上面字符串的最后10位匹配。对于前10位数字,我们可以再次使用
十进制
,但精度要低得多,这将导致它(请相信我)在封面下使用不同的方法:

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

将其舍入回10位与前面的结果匹配,并且指数也与
y
的长度一致。

为什么需要20亿位整数的精确值?您是否尝试过使用python的
pow
?不建议用这么大的数字进行传统的幂运算。@chepner:nah,它只有309771764位。但我敢打赌,计算需要的内存比这多得多。对不起,现在没有时间详细回答
pow()
在这种情况下没有帮助。并行化并非易事。真正的问题是基转换:Python在内部使用了基2的变体,而转换为基10(对于字符串)需要的时间是位数的二次方。非常非常慢。试着写出来,例如,
hex(a)
。快得多。或者使用
decimal
模块,该模块以10为基数开始工作。为什么需要20亿位整数的精确值?您是否尝试过使用python的
pow
?不建议用这么大的数字进行传统的幂运算。@chepner:nah,它只有309771764位。但我敢打赌,计算需要的内存比这多得多。对不起,现在没有时间详细回答
pow()
在这种情况下没有帮助。这不是一个简单的方法