简体   繁体   English

Python:计算pi时“long int太大而不能转换为float”

[英]Python: “long int too large to convert to float” when calculating pi

I get this error when using a python script that calculates pi using the Gauss-Legendre algorithm. 当使用python脚本使用Gauss-Legendre算法计算pi时,我收到此错误。 You can only use up to 1024 iterations before getting this: 在获得此项之前,您最多只能使用1024次迭代:

    C:\Users\myUsernameHere>python Desktop/piWriter.py
    End iteration: 1025
    Traceback (most recent call last):
      File "Desktop/piWriter.py", line 15, in <module>
        vars()['t' + str(sub)] = vars()['t' + str(i)] - vars()['p' + str(i)] * math.
    pow((vars()['a' + str(i)] - vars()['a' + str(sub)]), 2)
    OverflowError: long int too large to convert to float

Here is my code: 这是我的代码:

import math

a0 = 1
b0 = 1/math.sqrt(2)
t0 = .25
p0 = 1

finalIter = input('End iteration: ')
finalIter = int(finalIter)

for i in range(0, finalIter):
        sub = i + 1
        vars()['a' + str(sub)] = (vars()['a' + str(i)] + vars()['b' + str(i)])/ 2
        vars()['b' + str(sub)] = math.sqrt((vars()['a' + str(i)] * vars()['b' + str(i)]))
        vars()['t' + str(sub)] = vars()['t' + str(i)] - vars()['p' + str(i)] * math.pow((vars()['a' + str(i)] - vars()['a' + str(sub)]), 2)
        vars()['p' + str(sub)] = 2 * vars()['p' + str(i)]
        n = i

pi = math.pow((vars()['a' + str(n)] + vars()['b' + str(n)]), 2) / (4 * vars()['t' + str(n)])
print(pi)

Ideally, I want to be able to plug in a very large number as the iteration value and come back a while later to see the result. 理想情况下,我希望能够插入一个非常大的数字作为迭代值,稍后再回来查看结果。

Any help appreciated! 任何帮助赞赏! Thanks! 谢谢!

Floats can only represent numbers up to sys.float_info.max, or 1.7976931348623157e+308. 浮点数只能表示最大为sys.float_info.max或1.7976931348623157e + 308的数字。 Once you have an int with more than 308 digits (or so), you are stuck. 一旦你有一个超过308位数的int(或左右),你就会陷入困境。 Your iteration fails when p1024 has 309 digits: 当p1024有309位时,您的迭代失败:

179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216L

You'll have to find a different algorithm for pi, one that doesn't require such large values. 你必须为pi找到一个不同的算法,一个不需要这么大值的算法。

Actually, you'll have to be careful with floats all around, since they are only approximations. 实际上,你必须小心四处浮动,因为它们只是近似值。 If you modify your program to print the successive approximations of pi, it looks like this: 如果您修改程序以打印pi的连续近似值,它看起来像这样:

2.914213562373094923430016933707520365715026855468750000000000
3.140579250522168575088244324433617293834686279296875000000000
3.141592646213542838751209274050779640674591064453125000000000
3.141592653589794004176383168669417500495910644531250000000000
3.141592653589794004176383168669417500495910644531250000000000
3.141592653589794004176383168669417500495910644531250000000000
3.141592653589794004176383168669417500495910644531250000000000

In other words, after only 4 iterations, your approximation has stopped getting better. 换句话说,仅经过4次迭代后,您的近似值就会越来越好。 This is due to inaccuracies in the floats you are using, perhaps starting with 1/math.sqrt(2) . 这是由于您使用的浮点数不准确,可能从1/math.sqrt(2) Computing many digits of pi requires a very careful understanding of the numeric representation. 计算pi的许多数字需要非常仔细地理解数字表示。

As noted in previous answer, the float type has an upper bound on number size. 如前面的答案所述, float类型的数字大小有一个上限。 In typical implementations, sys.float_info.max is 1.7976931348623157e+308, which reflects the use of 10 bits plus sign for the exponent field in a 64-bit floating point number. 在典型的实现中, sys.float_info.max是1.7976931348623157e + 308,它反映了在64位浮点数中使用10位加号作为指数字段。 (Note that 1024*math.log(2)/math.log(10) is about 308.2547155599.) (注意1024 * math.log(2)/math.log(10)约为308.2547155599。)

You can add another half dozen decades to the exponent size by using the Decimal number type . 您可以使用十进制数字类型将另外六十年添加到指数大小。 Here is an example (snipped from an ipython interpreter session): 这是一个示例(从ipython解释器会话中剪切):

In [48]: import decimal, math    
In [49]: g=decimal.Decimal('1e12345')    
In [50]: g.sqrt()
Out[50]: Decimal('3.162277660168379331998893544E+6172')
In [51]: math.sqrt(g)
Out[51]: inf

This illustrates that decimal's sqrt() function performs correctly with larger numbers than does math.sqrt() . 这说明decimal的sqrt()函数使用比math.sqrt()更大的数字正确执行。

As noted above, getting lots of digits is going to be tricky, but looking at all those vars hurts my eyes. 如上所述,获得大量数字将是棘手的,但看着所有这些vars伤害了我的眼睛。 So here's a version of your code after (1) replacing your use of vars with dictionaries, and (2) using ** instead of the math functions: 所以这是你的代码的一个版本(1)替换你对字典使用vars ,以及(2)使用**而不是数学函数:

a, b, t, p = {}, {}, {}, {}
a[0] = 1
b[0] = 2**-0.5
t[0] = 0.25
p[0] = 1

finalIter = 4

for i in range(finalIter):
    sub = i + 1
    a[sub] = (a[i] + b[i]) / 2
    b[sub] = (a[i] * b[i])**0.5
    t[sub] = t[i] - p[i] * (a[i] - a[sub])**2
    p[sub] = 2 * p[i]
    n = i

pi_approx = (a[n] + b[n])**2 / (4 * t[n])

Instead of playing games with vars , I've used dictionaries to store the values (the link there is to the official Python tutorial) which makes your code much more readable. 我没有使用vars玩游戏,而是使用词典存储值(链接到官方Python教程),这使得代码更具可读性。 You can probably even see an optimization or two now. 您现在甚至可以看到一两个优化。

As noted in the comments, you really don't need to store all the values, only the last, but I think it's more important that you see how to do things without dynamically creating variables. 如评论中所述,您实际上不需要存储所有值,只需存储最后一个值,但我认为在不动态创建变量的情况下查看如何执行操作更为重要。 Instead of a dict , you could also have simply appended the values to a list , but lists are always zero-indexed and you can't easily "skip ahead" and set values at arbitrary indices. 您也可以简单地将值附加到list ,而不是dict ,但列表始终为零索引,并且您不能轻易地“向前跳过”并在任意索引处设置值。 That can occasionally be confusing when working with algorithms, so let's start simple. 在使用算法时,这有时会让人感到困惑,所以让我们开始吧。

Anyway, the above gives me 无论如何,上面给了我

>>> print(pi_approx)
3.141592653589794
>>> print(pi_approx-math.pi)
8.881784197001252e-16

A simple solution is to install and use the arbitrary-precision mpmath module which now supports Python 3. However, since I completely agree with DSM that your use of vars() to create variables on the fly is an undesirable way to implement the algorithm, I've based my answer on his rewrite of your code and [trivially] modified it to make use of mpmath to do the calculations. 一个简单的解决方案是安装和使用现在支持Python 3的任意精度mpmath模块。但是,由于我完全同意DSM,使用vars()创建变量是实现算法的一种不受欢迎的方法,我的答案是基于对你的代码的重写 ,并且[通常]修改它以利用mpmath来进行计算。

If you insist on using vars() , you could probably do something similar -- although I suspect it might be more difficult and the result would definitely harder to read, understand, and modify. 如果你坚持使用vars() ,你可能会做类似的事情 - 虽然我怀疑它可能会更难,结果肯定更难以阅读,理解和修改。

from mpmath import mpf  # arbitrary-precision float type

a, b, t, p = {}, {}, {}, {}
a[0] = mpf(1)
b[0] = mpf(2**-0.5)
t[0] = mpf(0.25)
p[0] = mpf(1)

finalIter = 10000

for i in range(finalIter):
    sub = i + 1
    a[sub] = (a[i] + b[i]) / 2
    b[sub] = (a[i] * b[i])**0.5
    t[sub] = t[i] - p[i] * (a[i] - a[sub])**2
    p[sub] = 2 * p[i]
    n = i

pi_approx = (a[n] + b[n])**2 / (4 * t[n])
print(pi_approx)  # 3.14159265358979

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

相关问题 OverflowError:long int太大,无法在python中转换为float - OverflowError: long int too large to convert to float in python Python:溢出错误long int太大而无法转换为float - Python : overflow error long int too large to convert to float 长整型太大,无法转换为浮点型 - Long int too large to convert to float Python:检查(真大)素数时“ long int太大,无法转换为浮点数” - Python: “long int too large to convert to float” when checking (really big) prime numbers 检查python int是否太大而无法转换为float - Check if python int is too large to convert to float Python OverflowError:int太大,无法转换为float - Python OverflowError: int too large to convert to float calcuale ---- OverflowError:long int太大,无法转换为float - calcuale ----OverflowError: long int too large to convert to float Python:OverflowError long int too large to convert to int - Python: OverflowError long int too large to convert to int 将字符串转换为 int 时出现“溢出错误:Python int 太大而无法转换为 C long” - "OverflowError: Python int too large to convert to C long" when casting string to int Python问题math.floor:int太大而无法转换为float - Python issues with math.floor: int too large to convert to float
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM