Python使用math.floor函数时出现问题:整数过大无法转换为浮点数。

3
我想在Python中计算(⌊2^(1918)*π⌋+124476),但是使用以下代码时出现了错误:
b = math.floor((2**1918) * math.pi) + 124476
print(b)

溢出错误:整数太大,无法转换为浮点数

如何使其正常工作?最终我只想将其全部转换为十六进制(如果这有助于回答我的问题),但我实际上只是想先将其转换为整数 :)


1
我看到的所有类似问题的解决方案都使用 decimal 模块,比如在这个问题中。 - G. Anderson
一个int类型只有8位,我相信。试试使用2.0 ** 1918? - WiseDev
5
一个int不仅仅包含8位。 - Thomas Jager
4个回答

2
正确的解决方案取决于所需结果的精度。由于2^1918对于标准整数和浮点数容器来说已经太大了,因此不能进行直接计算,否则将失去10^300以下所有精度。

为了计算所需的结果,应使用任意精度计算技术。您可以自己实现算法或使用其中一个可用的库。

假设您正在寻找表达式的整数部分,需要大约600个十进制位才能精确存储结果。以下是使用mpmath获取它的方法:

最初的回答:

from mpmath import mp
mp.dps = 600
print(mp.floor(mp.power(2, 1918)*mp.pi + 124476))

最初的回答: 接下来,您需要将其转换为十六进制表示形式(或从其内部二进制形式中提取十六进制),这是另一个主题的问题 :)
转换一下该数值的十六进制表示形式(或从其内部二进制形式中提取十六进制),具体方法请参考其他资料。

1
请注意,@MisterMiyagi的答案是错误的,因为math.pi是一个浮点常量,并且对于您的情况具有非常低的精度。通过比较结果,您可以清楚地看到它(它们在第16位数字开始不同,这是双精度浮点数的机器epsilon顺序)。 - M0nZDeRR
1
这使得它不精确,但并不是错误。误差为3.8981718325193755e-17,可能是可以接受的。 - MisterMiyagi
2
我遇到了“没有名为'mpmath'的模块”的错误。你知道该怎么解决吗? :p - user5748960
1
好的 - 不太准确,那就这样吧!然而,错误不是10^-17的数量级,而是至少10^+15(这取决于您如何评估错误)。由于您的结果只有300个中的前15个正确,我认为它是相当错误的,因为问题明确表明在较低位数上具有一定的精度是可取的(否则+124476项完全无关紧要)。 - M0nZDeRR
1
我刚意识到在我的问题中 FLOOR 实际上很重要,但是在你的回答中被省略了。也许可以编辑一下,这样它就会说 'print(mp.floor(mp.power(2, 1918)*mp.pi) + 124476)'。 - user5748960
显示剩余6条评论

2
基本问题就在于这条消息所说的内容。Python整数可以是任意大的,甚至比浮点数的范围还要大。2**1918在十进制中包含578个有效数字,比你的IEEE754硬件能表示的最大浮点数还要大得多。因此,调用失败了。
你可以尝试查看mpmath模块。它专门用于浮点运算,超出了普通硬件处理的范围。
"Original Answer"翻译成"最初的回答"

2
我认为可以不用高精度算术解决这个问题。其中mn是整数,floor(n.something + m)等于floor(n.something) + m。所以在这种情况下,您要找的是floor(2 ** 1918 * pi)加上一个整数(即124476)。floor(2 ** whatever * pi)只是pi的前whatever + 2位。因此,只需查找pi的前1920位,添加124476的位,然后输出十六进制数字。
一个Spigot算法可以生成pi的数字而不使用任意精度。快速的网络搜索似乎可以找到一些基于Python的实现,用于在10进制中生成数字。我没有看到有关2进制的内容,但如果我没有错的话,Plouffe公式会生成16进制数字。

第一个1920位的π,我猜,而不是前1918位?(我相当确定上下文是RFC 3526,在这种情况下,这些位被填充了64个1位,每端共计1920 + 64 + 64 = 2048位。) - Mark Dickinson
是的,你说得对,我修正了文本。我发现这是某种虚构问题...有趣的是看到这种联系。 - Robert Dodier

1
问题在于(2**1918) * math.pi试图将整数转换为64位浮点精度,这是不够大的。您可以将math.pi转换为fraction以使用任意精度。
>>> math.floor((2**1918) * fractions.Fraction(math.pi) + 124476)
74590163000744212756918704280961225881025315246628098737524697383138220762542289800871336766911957454080350508173317171375032226685669280397906783245438534131599390699781017605377332298669863169044574050694427882869191541933796848577277592163846082732344724959222075452985644173036076895843129191378853006780204194590286508603564336292806628948212533561286572102730834409985441874735976583720122784469168008083076285020654725577288682595262788418426186598550864392013191287665258445673204426746083965447956681216069719524525240073122409298640817341016286940008045020172328756796

请注意,任意精度适用于计算; math.pi 仅以64位浮点精度定义。如果需要确切的值,请使用外部库,例如 mpmath
要将其转换为十六进制字符串,请使用hex或字符串格式:
>>> hex(math.floor((2**1918) * fractions.Fraction(math.pi) + 124476))
'0xc90fdaa22168c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e63c'
>>> '%x' % math.floor((2**1918) * fractions.Fraction(math.pi) + 124476)
'c90fdaa22168c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e63c'
>>> f'{math.floor((2**1918) * fractions.Fraction(math.pi) + 124476):X}'
'C90FDAA22168C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001E63C'

对于字符串格式,x 提供小写十六进制,而 X 则提供大写十六进制。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接