首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >进度指标使PI计算太慢

进度指标使PI计算太慢
EN

Code Review用户
提问于 2018-10-26 13:42:08
回答 1查看 79关注 0票数 1

我编写了代码来计算PI到用户指定的小数位数。效果很好。我想添加一个进度指示,这样用户就不必连续数小时盯着闪烁的光标,而不显示进度。我得到了一些有用的东西,但它使代码变得非常、太慢。在下面的代码中,我在“冒犯”代码之前和之后用*‘S的双行线注释了进度指标部分。我怀疑是log10计算使事情变得太慢了。任何建议:

代码语言:javascript
复制
# A program to calculate PI to a user specified number of decimal digits
# The program uses the Chudnovsky algorithm.  
# Further details on the algorithm are availabler here:
# https://en.wikipedia.org/wiki/Chudnovsky_algorithm

# A generator which divides the user requested number of decimal places into 10% increments

def ten_percent(places):

    for i in range(int(places/10),int(places+1),int(places/10)):
        yield i

def pi_calc(places):

    # places is user specified number of decimal places that should be calculated.

    import decimal
    import time
    import numpy as np
    start_time = time.time()

    decimal.getcontext().prec = places + 3

    # The function makes succesive calculations of PI using the algorithm.
    # The current calculated PI value is subtracted from the succesive PI value
    # If the difference is less than the 1 x 10**(-places) the result is returned

    # Initialise some variables

    current_pi = 3
    next_pi = 3
    precision = 1 * 10**(-places-3)
    counter = 1
    precision_step = ten_percent(places)
    precision_check = next(precision_step)

    # Initialise terms used in the itteration

    L = 13591409
    X = 1
    M = 1
    K = 6
    S = decimal.Decimal(M*L)/X

    next_pi = 426880*decimal.Decimal(10005).sqrt()/S

    # Perform the itterative calculation until the required precision is achieved

    while abs(next_pi - current_pi) > precision:
        current_pi = next_pi

        # Calculate the next set of components for the PI approximation

        L += 545140134
        X *= -262537412640768000
        M = M*(K**3-16*K)//(counter)**3
        S += decimal.Decimal(M*L)/X
        K += 12
        counter += 1

        # Calculate the next approximation of PI

        next_pi = 426880*decimal.Decimal(10005).sqrt()/S

#******************************************************************************************************************************
#******************************************************************************************************************************
# This progress indication slows the code down too much to be practical
#
#
#       # Give the user some feedback on progress of the calculation
#
#       # The try statement is required because the error between successive pi calculations can become
#       # "infintly" small and then a string is returned instead of a number.
#
#       try:
#           test_num = abs(round(np.log10(abs(decimal.Decimal(next_pi - current_pi)))))
#       except:
#           pass
#       
#       if test_num >= precision_check:
#           print('Calculation steps: ' + str(counter-1) + ' Approximate decimal places: ' + str(precision_check))
#           if precision_check < places:
#               precision_check = next(precision_step)
#*******************************************************************************************************************************
#*******************************************************************************************************************************

    return decimal.Decimal(str(next_pi)[:places+2])

# Get the required number of decimal places from the user and call the function to perform
# the calculation

while True:

    try:
        places = int(input('To how many decimal places would you like to calculate PI? '))
    except:
        print('Please provide a valid integer value.')
        continue
    else:
        break

calculated_pi = pi_calc(places) 
print('The value of PI to '+ str(places) + ' decimal places is:\n%s' % (calculated_pi))
EN

回答 1

Code Review用户

发布于 2018-10-26 21:06:14

这一答案提出了各种修复性能的策略。它不考虑代码的其他方面。它不考虑数值分析。(如果有一种更便宜的方法来进行实际计算来衡量进度,那不是我能告诉你的。)

首先,这段代码经历了很多迭代。您知道,大多数情况下,您将没有达到下一个进度标记。如果您只通过循环每100次检查一次进度,您已经将花费在这一昂贵操作上的时间减少到了1%。(对于迭代次数较少的事情,您将失去准确性,但对于快速情况,进度条不太重要。)

另一种选择是在一个单独的过程中计算进度。主进程可以将next_picurrent_pi之间的差异推到堆栈上,当进程完成最后一次计算时,这个堆栈就会弹出。

最后,你可以估计/撒谎。图运行时间(或迭代次数)与数字数之比。这是个不错的功能吗?然后,你可以猜出这样的计算要花费多长时间,并以此为基础进行计算。我不是一个数学人,所以我不知道这是否实用。如果不是,也许它能让你朝着更好的方向思考。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/206326

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档