Python math.floor 的问题:整数太大而无法转换为浮点数

Python issues with math.floor: int too large to convert to float

我想在 python 中计算 (⌊2^(1918)*π⌋+124476) 但是当我使用以下代码计算时出现此错误:

b = math.floor((2**1918) * math.pi) + 124476
print(b)

OverflowError: int 太大而无法转换为 float

你怎样才能让它发挥作用?最后我只是想把它全部设为十六进制(如果这有助于回答我的问题)但实际上我只是想先把它作为一个整数:)

基本问题是消息的内容。 Python 整数可以是任意大的,甚至比浮点数的范围还要大。 2**1918 十进制包含 578 位有效数字,比 IEEE754 硬件可以表示的最大浮点数大得多。所以调用失败了。

您可以尝试查看 mpmath 模块。它专为超出普通硬件处理范围的浮点运算而设计。

问题是 (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 提供 lower-case 十六进制,而 X 提供 upper-case 大小写。

正确的解决方案实际上取决于对结果的精确度要求。由于 2^1918 对于标准整数和浮点数容器来说已经太大了,因此在不丢失低于 ~ 10^300 的所有精度的情况下,不可能通过直接计算逃脱。

为了计算出想要的结果,您应该使用arbitrary-precision计算技巧。您可以自己实现算法或使用可用的库之一。

假设您要查找表达式的整数部分,将需要大约 600 位小数来精确存储结果。这是使用 mpmath:

获取它的方法
from mpmath import mp
mp.dps = 600
print(mp.floor(mp.power(2, 1918)*mp.pi + 124476))

74590163000744215664571428206261183464882552592869067139382222056552715349763159120841569799756029042920968184704590129494078052978962320087944021101746026347535981717869532122259590055984951049094749636380324830154777203301864744802934173941573749720376124683717094961945258961821638084501989870923589746845121992752663157772293235786930128078740743810989039879507242078364008020576647135087519356182872146031915081433053440716531771499444683048837650335204793844725968402892045220358076481772902929784589843471786500160230209071224266538164123696273477863853813807997663357545.0

接下来,你所要做的就是将其转换为十六进制表示(或从其内部二进制形式中提取十六进制),这是另一个主题的事情:)

我觉得不用high-precision算术也能解决这个问题。 floor(n.something + m) 其中 mn 是整数等于 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 为底数的数字。