Каков наилучший способ проверить, к какому значению подходят элементы списка? - PullRequest
0 голосов
/ 25 января 2019

Я работаю над методом вычисления пределов функции в Python, но некоторые функции выдают неверный вывод. Моя главная цель - вычислить производные, но для этого я должен вычислить предел функции.

Это для личного проекта, я бы не хотел, чтобы модуль решал лимит или искал алгоритм в Википедии. Я пытался использовать следующий метод:

  • Я создаю список со значениями f (x), очень близкими к значению, которое стремится к x
  • Код анализирует, какое значение больше всего повторяется в этом списке, и делается вывод, что это значение является пределом функции f (x), стремящейся к x.

Этот метод явно антиматематический, но я не мог придумать лучшего решения. Я пытался применить меры централизации, но я не думаю, что это работает для периодической непрерывной дроби, как 2/7.

Вот мой код:

# this function resolves a numerical expression
# using eval function from Python

def Solve(Str):
    if '^' in Str:
        Str = Str.replace('^', '**')
    return eval(Str)


# this function solves a mathematical function by substituting x
# for a value passed by parameter and returning its result

def SolveF(f, x, var = 'x'):
    f = f.replace(' ', '')

    # inserts a multiplication sign between numbers
    # example: 5x --> 5*x

    f = list(f)
    i = 0
    while i < len(f)-1:
        L = f[i:i+2]
        if L[0] in '0123456789' and L[1] == var:
            f.insert(i+1, '*')
        i += 1
    f = ''.join(f)

    f = f.replace(var, '(' + var + ')')
    f = f.replace(var, str(x))

    return Solve(f)


# this function returns f(x) for a value very close
# to the value at which x tends. for example, if x
# tends to 5, it returns f(5.0000000000001). the tiny
# ammount that is added to x is 10^(-13) (arbitrary value)

def Lim(f, x, c = 13):
    return SolveF(f, x + (10**(-c)))


# this function returns several f(x) in a list to values
# very close to the value at which x tends. for example,
# if x tends to 0, it will add the list f(0.001), f(0.000001),
# f(0.0000001), ..., f(0.0000000001). then returns the value
# that most repeats in that list, which is supposed to be the
# value whose function is approaching.

def LimM(f, x):
    i = 0
    L = []
    for i in range(5, 20):
        try:
            L.append("{:.10f}".format(Lim(f, x, i)))
        except ZeroDivisionError:
            i += 1
            continue

    print(L)
    List2 = [L.count(i) for i in set(L)]
    if List2 == [1]*len(List2):
        return 'inf'
    else:
        return list(set(L))[List2.index(max(List2))]

from fractions import Fraction
while True:
    F = input('Function: ')
    X = float(input('x --> '))
    Res = LimM(F, X)
    if Res != 'inf':
            print(Fraction(Res).limit_denominator())
    else:
        print(Res)

Пример 1: функция (x^2 - 4)/(x - 2) приближается x = 2.

Список, сгенерированный функцией LimM, равен ['4.0000100000', '4.0000010001', '4.0000000977', '4.0000000000', '4.0000000000', '4.0000000000', '4.0000000000', '4.0000000000', '4.0000000000', '4.0000000000', '4.0000000000'].

Обратите внимание, что значение, которое больше всего повторяется в списке, равно '4.0000000000', поэтому ограничение равно 4.

Пример 2: функция ((x + 1)/(x - 1) приближается x = 2.

Список, сгенерированный функцией LimM, равен ['2.9999800002', '2.9999980000', '2.9999998000', '2.9999999800', '2.9999999980', '2.9999999998', '3.0000000000', '3.0000000000', '3.0000000000', '3.0000000000', '3.0000000000', '3.0000000000', '3.0000000000', '3.0000000000', '3.0000000000'].

Обратите внимание, что значение, которое больше всего повторяется в списке, равно '3.0000000000', поэтому ограничение равно 3.

Я проверил 28 различных лимитов (вы можете проверить вопросы здесь ), и только 6 были неправильными. Среди них:

  • Ввод 1: Упражнение 1, элемент m)
Function: (1/(1-x)) - (3/(1-x^3))
x --> 1

    Right answer: -1
    Code output: 0

Список сформирован: ['-0.9999930434', '-1.0000138859', '-0.9992006216', '-0.7401486933', '0.0000000000', '0.0000000000', '0.0000000000', '0.0000000000', '0.0000000000', '0.0000000000', '0.0000000000']

  • Ввод 2: Упражнение 1, пункт p)
Function: (3x^4 - 4x^3 + 1)/(x - 1)^2
x --> 1

    Right answer: 6
    Code output: 0

Список сформирован: ['6.0000848733', '6.0000893153', '5.9952043260', '8.8817843050', '0.0000000000', '0.0000000000', '0.0000000000', '0.0000000000', '0.0000000000', '0.0000000000', '0.0000000000']

  • Ввод 3: Упражнение 1, элемент u)
Function: (x^2 + 7x - 44)/(x^2 - 6x + 8)
x --> 4

    Right answer: 15/2
    Code output: 4222/563

Список создан: ['7.4999675007', '7.4999967484', '7.4999995648', '7.4999992895', '7.4999982236', '7.4999911182', '7.4991119005', '7.4991119005', '7.5714285714', '6.6666666667']

  • Ввод 4: Упражнение 1, элемент z)
Function: (1/(x^2 - 1)) - (2/(x^4 - 1))
x --> 1

    Right answer: 1/2
    Code output: 0

Список создан: ['0.4999950374', '0.4999879392', '0.4996002605', '0.8326672688', '0.0000000000', '0.0000000000', '0.0000000000', '0.0000000000', '0.0000000000', '0.0000000000', '0.0000000000']

  • Ввод 5: Упражнение 3, пункт а)
Function: ((1 + 2x)^(0.5) - 1)/(3x)
x --> 0

    Right answer: 1/3
    Code output: 0

Список сформирован: ['0.3333316667', '0.3333331667', '0.3333333165', '0.3333333313', '0.3333332869', '0.3333333609', '0.3333333609', '0.3332889520', '0.3330669074', '0.3330669074', '0.2960594732', '0.0000000000', '0.0000000000', '0.0000000000', '0.0000000000']

Следовательно, как лучше всего проверить, к какому значению подходят элементы списка?

1 Ответ

0 голосов
/ 25 января 2019

Просто возьмите последнее значение. Это лучшее приближение, которое вы получите.

Улучшение алгоритма на более высоком уровне: даже не пытайтесь вычислить другие элементы списка. Просто возьмите коэффициент разности с небольшой разницей и используйте его в качестве вычисленной производной.

Это, конечно, не будет полностью надежным, но это неизбежная проблема выбранного вами подхода. Просто невозможно вычислить лимиты, посмотрев на конечное число точек вблизи того места, где вы хотите взять лимит.

...