为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

波斯汪 2022-07-19 10:58:43
我正在尝试找到一种在 Python 中执行以下操作的有效方法:   a = 12345678901234567890123456**12345678   f = open('file', 'w')   f.write(str(a))   f.close()使用一个线程时,计算功率大约需要 40 分钟。有没有一种快速简便的方法可以将此操作分散到多个线程上?由于这个数字非常大,我认为字符串函数并不能完全胜任这项任务——它已经运行了将近三个小时。我需要将数字放在文本文件中。关于如何更好地实现这一目标的任何想法?
查看完整描述

1 回答

?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

我想给出一个奢侈的 ;-) 答案,但现在没有时间。详细说明我的评论,该decimal模块是您真正想要的。计算功率要快得多 ,将结果转换为十进制字符串要快得多:


>>> import decimal

您需要更改其内部结构以避免使用浮点数,从而为其提供足够多的内部数字来存储最终结果。我们在这里需要精确的整数运算,而不是四舍五入的浮点数。所以我们摆弄东西,decimal尽可能使用它能够使用的精度,并告诉它在舍入时丢失信息时引发“不精确”异常。请注意,您需要 64 位版本的 Pythondecimal才能使用足够的精度来保存示例中的确切结果:


>>> 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

现在为基础创建一个Decimal:


>>> base = decimal.Decimal(12345678901234567890123456)

>>> base

Decimal('12345678901234567890123456')

并提高幂 - 指数将自动转换为Decimal,因为基数已经是Decimal:


>>> x = base ** 12345678

这在我的盒子上只需要不到一分钟!其中的原因是有的。这并不是因为它以 10 为底,而是因为编写该decimal模块的人实现了“高级”算法来进行非常大的乘法运算。


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


>>> y = str(x)

>>> len(y)

309771765

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


>>> y[-10:]

'6044706816'

>>> y[:10]

'2759594879'

正如@StefanPochmann 在评论中指出的那样,通过使用模块化(3-argument),可以使用本机整数非常快速地获得最后 10 位数字pow():


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

6044706816

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


>>> c.prec = 12

>>> c.traps[decimal.Inexact] = 0  # don't trap on rounding!

>>> base ** 12345678

Decimal('2.75959487945E+309771764')

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


查看完整回答
反对 回复 2022-07-19
  • 1 回答
  • 0 关注
  • 74 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信