首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >序列与串联求解器

序列与串联求解器
EN

Code Review用户
提问于 2020-03-11 16:02:30
回答 1查看 1.2K关注 0票数 3

为了帮助我解决家庭作业,我做了一个序列和系列的求解器,我迫切需要一些方法来使它更加紧凑和高效,因为我使用了蛮力。

如果你想看看这应该做什么,请看我的github

这个Python代码是为fx-cg50计算器的micropython编写的,其中有许多函数不能工作,包括分数、一些数学函数(如math.gcdmath.isclose )。因此,我确实需要一些建议或编程技巧来简化我的程序。

免责声明:我只是一个16岁的A级学生,认为我是一个初学者.我知道eval是不安全的,但我并不打算把它上传到网上,它只供我个人使用。

代码语言:javascript
复制
# just to make the input_checker function smaller and to eliminate repeated code, responsible for iterating through a list of inputs
def three_variables_looper_arithmetic():
    count_list = [input("enter a1: "), input("enter n: "), input("enter d: ")]
    count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
    return count_list

# just to make the input_checker function smaller and to eliminate repeated code, responsible for iterating through a list of inputs
def three_variables_looper_geometric():
    count_list = [input("enter a1: "), input("enter r: "), input("enter n: ")]
    count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
    return count_list


# loops through all the inputs of a given situation based on whether its arithmetic
# or not, and checks whether the input is string like "6/2" so it could evaluate it, allows input of fractions
def input_checker(choice_main, choice_sub, L):
    if choice_main == 'arithmetic':
        if choice_sub == 'a_nth':
            return three_variables_looper_arithmetic()

        elif choice_sub == 'sum_to_nth_without_L':
            return three_variables_looper_arithmetic()

        elif choice_sub == 'sum_to_nth_with_L':
            count_list = [input("enter a1: "), input("enter n: "), L]
            count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
            return count_list

        elif choice_sub == "a_nth_exceed":
            count_list = [input("enter a1: "), input("enter r/d: ")]
            count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
            return count_list

        elif choice_sub == "sum_to_nth_without_L_exceed":
            count_list = [input("enter a1: "), input("enter r/d: ")]
            count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
            return count_list

        elif choice_sub == "sum_to_nth_with_L_exceed":
            count_list = [input("enter a1: "), L]
            count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
            return count_list


    elif choice_main == 'geometric':
        if choice_sub == 'a_nth':
            return three_variables_looper_geometric()

        elif choice_sub == 'sum_to_nth':
            return three_variables_looper_geometric()

        elif choice_sub == 'sum_to_infinity':
            count_list = [input("enter a1: "), input("enter r: ")]
            count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
            return count_list

        elif choice_sub == "a_nth_exceed":
            count_list = [input("enter a1: "), input("enter r/d: ")]
            count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
            return count_list

        elif choice_sub == "sum_to_nth_without_L_exceed":
            count_list = [input("enter a1: "), input("enter r/d: ")]
            count_list = [float(eval(count)) for count in count_list if isinstance(count, str)]
            return count_list

# checks if L is an x or not, also based on whether its on the exceed or normal path, and
# an x means L is not present, while a value of L represents it is present and used in calculation
def L_evaluator(L, option, choice_n, value):
    if option == "normal":
        if L == "x":
                    a1, n, d = input_checker(choice_main, choice_n, L)
                    result = (n/2)*(2*a1+(n-1)*d)
                    return result
        else:
                    choice_n = choice_map_sub['x']
                    a1, n, L = input_checker(choice_main, choice_n, L)
                    result = (n/2)*(a1+L)
                    return result

    if option == "exceed":
        if L == "x":
                    a1, d = input_checker(choice_main, choice_n, 0)
                    a1, d = float(a1), float(d)
                    n = 1
                    while True:
                        result = (n/2)*(2*a1+(n-1)*d)
                        if (result >= float(value)):
                            break
                        n += 1
                    return n
        else:
                    choice_n = choice_map_exceed['c']
                    a1, L = input_checker(choice_main, choice_n, L)
                    n = 1
                    while True:
                        result = (n/2)*(a1+L)
                        if (result >= float(value)):
                            break
                        n += 1
                    return n


# finds the first n to exceed a certain value, by using brute force method
def minimum_n_finder(choice_main, choice_map_exceed):
    choice_n_input = None
    if choice_main == "arithmetic":
        while choice_n_input not in ['a', 'b']:
            choice_n_input = input("Enter a for nth\nEnter b for sum\n>> ")
        choice_n = choice_map_exceed[choice_n_input]
        print("enter x in n")

        if choice_n == "a_nth_exceed":
            print("a1+(n-1)d > Value")
            a1, d = input_checker(choice_main, choice_n, 0)
            n = 1
            value = input("Enter the value to exceed: ")
            while True:
                result = a1+(n-1)*d
                if (result >= float(value)):
                    break
                n += 1
            print("The minimum n to exceed is " + str(n))

        if choice_n == "sum_to_nth_without_L_exceed":
            n = 1
            print("Sn=(n/2)(2a1+(n-1)d)>Value\nSn=(n/2)(a1+L)>Value\nEnter x if L is unknown")
            L = input("Enter L: ")
            value = input("Enter the value to exceed: ")
            result = L_evaluator(L, "exceed", choice_n, value)
            print("The minimum n to exceed is " + str(result))


    elif choice_main == 'geometric':
        while choice_n_input not in ['a', 'b']:
            choice_n_input = input("Enter a for nth\nEnter b for sum_to_nth\n>> ")
        choice_n = choice_map_exceed[choice_n_input]

        if choice_n == "a_nth_exceed":
            print("a1(r)^(n-1)>Value")
            a1, r = input_checker(choice_main, choice_n, 0)
            if a1 == 0:
                print("a cannot be 0")
                raise SystemExit
            n = 1
            value = input("Enter the value to exceed: ")
            while True:
                result = a1*(r)**(n-1)
                if (result >= float(value)):
                    break
                n += 1
            print("The minimum n to exceed is " + str(n))

        elif choice_n == "sum_to_nth_without_L_exceed":
            print("Sn=(a1(1-(r)^n))/(1-r)")
            a1, r = input_checker(choice_main, choice_n, 0)
            if a1 == 0:
                print("a cannot be 0")
                raise SystemExit
            n = 1
            value = input("Enter the value to exceed: ")
            while True:
                result = (a1*(1-(r)**n))/(1-r)
                if (result >= float(value)):
                    break
                n += 1
            print("The minimum n to exceed is " + str(n))


# as this code is for a calculator the x button is very easily accessible to shut the whole program.
def stopper():
    stop_or_continue = input("Stop?: enter x then\n>>>  ")
    if stop_or_continue == "x":
        raise SystemExit  

print("Sequence & Series Solver")

# asks whether you want to solve arithmetically or geometrically, depends on the sequence/series
while True:
    choice_main , choice_input_main = None, None
    choices_main_options = ['a','b']
    choice_map_main ={"a": 'arithmetic', "b": 'geometric'}
    while choice_input_main not in choices_main_options:
        choice_input_main = input("a for arithmetic\nb for geometric\n>> ")
    choice_main = choice_map_main[choice_input_main]

    if choice_main == "arithmetic":
        print("Arithmetic: ")
        choice_sub, choice_input_sub = None, None
        choices_sub_options = ['a', 'b', 'c']
        choice_map_sub = {'a': 'a_nth', 'b': 'sum_to_nth_without_L', 'x': 'sum_to_nth_with_L', 'c':'minimum_number_of_terms_to_exceed'}
        while choice_input_sub not in choices_sub_options:
            choice_input_sub = input("a for a_nth term\nb for sum\nc for min_term_to_exceed\n>> ")
        choice_sub = choice_map_sub[choice_input_sub]

        # the variable choice_main refers to whether the choice is arithmetic or geometric
        # choice_sub refers to the types of formulas you'll use in sequences/series
        if choice_sub == "a_nth":
            print("a_nth=a1+(n-1)d")
            a1, n, d = input_checker(choice_main, choice_sub, 0)
            result = a1+(n-1)*d
            print(round(result,4))

        elif choice_sub == "sum_to_nth_without_L":
            print("Sn=(n/2)(2a1+(n-1)d)\nSn=(n/2)(a1+L)\nEnter x if L is unknown")
            L = input("Enter L: ")
            print(round(L_evaluator(L, "normal", choice_sub, 0), 4))

        elif choice_sub == "minimum_number_of_terms_to_exceed":
            choice_map_exceed = {'a': 'a_nth_exceed', 'b': 'sum_to_nth_without_L_exceed', 'c': 'sum_to_nth_with_L_exceed'}
            minimum_n_finder("arithmetic", choice_map_exceed)


    elif choice_main == "geometric":
        print("Geometric: ")
        choice_sub, choice_input_sub = None, None
        choices_sub_options = ['a', 'b', 'c', 'd']
        choice_map_sub = {'a': 'a_nth', 'b': 'sum_to_nth', 'c': 'sum_to_infinity', 'd': 'minimum_number_of_terms_to_exceed'}
        while choice_input_sub not in choices_sub_options:
            choice_input_sub = input("a for a_nth term\nb for sum\nc for sum to infinity\nd for min_terms_exceed\n>> ")
        choice_sub = choice_map_sub[choice_input_sub]

        if choice_sub == "a_nth":
            print("a_nth=a1(r)^(n-1)")
            a1, r, n = input_checker(choice_main, choice_sub, 0)
            result = a1*(r)**(n-1)
            print(round(result,4))

        elif choice_sub == "sum_to_nth":
            print("Sn=(a1(1-(r)^n))/(1-r)")
            a1, r, n = input_checker(choice_main, choice_sub, 0)
            try:
                result = (a1*(1-(r)**n))/(1-r)
                print(round(result,4))
            except (ZeroDivisionError, NameError):
                print("r cannot be 1!")

        elif choice_sub == "sum_to_infinity":
            print("S_inf=a1/(1-r)")
            a1, r = input_checker(choice_main, choice_sub, 0)
            if (r > 1):
                print("r cannot be greater than 1")
                raise SystemExit
            try:
                result = a1/(1-r)
                print(round(result,4))
            except (ZeroDivisionError, NameError):
                print("r cannot be 1!")

        elif choice_sub == "minimum_number_of_terms_to_exceed":
            choice_map_exceed = {'a': 'a_nth_exceed', 'b': 'sum_to_nth_without_L_exceed', 'c': 'sum_to_nth_with_L_exceed'}
            minimum_n_finder("geometric", choice_map_exceed)

    stopper()
EN

回答 1

Code Review用户

回答已采纳

发布于 2020-03-14 14:52:17

首先,您可以返回列表理解,而不是第一次覆盖count_list。这样可以在不影响可读性的情况下节省几行代码。

对于所有的如果案例,你可以用字典代替。所以如果choice_sub in dict.keys(): dict[choice_sub]

通常,当函数和您的函数一样长的时候,最好开始考虑OOP和类。您可以将“前端”(所有打印和输入)与“后端”(执行计算的函数/方法)分开。如果您想要从CLI应用程序迁移到具有图形界面的应用程序(这可能有助于使公式的格式更加可读性),这也会使您自己更容易理解。

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

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

复制
相关文章

相似问题

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