Вроде твоя задача - посчитать
⎛ xN ⎞(aN / aD)
⎜⎼⎼⎼⎼⎟ where xN,xD,aN,aD ∈ ℤ, xD,aD ≠ 0
⎝ xD ⎠
с использованием только умножения, деления, сложения и вычитания с методом Ньютона в качестве предлагаемого метода для воплощать в жизнь.
Уравнение, которое мы пытаемся решить (для y):
(aN / aD)
y = (xN / xD) where y ∈ ℝ
Метод Ньютона находит корень функции. Если мы хотим использовать его для решения вышеуказанной проблемы, мы вычитаем правую часть из левой, чтобы получить функцию, ноль которой дает нам желаемое y:
(aN/aD)
f(y) = y - (xN/xD) = 0
Не очень помогло. Я думаю, это все, что вам нужно? Дело здесь в том, чтобы пока не формировать эту функцию, потому что у нас нет способа вычислить рациональную степень рационального числа!
Во-первых, давайте решим, что оба значения aD и xD положительны. Мы можем сделать это, просто отрицая и aN, и aD, если aD было отрицательным (так что знак aN / < em> aD не изменяется), и отрицание значений xN и xD, если xD было отрицательным. Помните, что по определению ни xD, ни aD не равны нулю. Затем мы можем просто возвести обе стороны в ад степени:
aD aN aN aN
y = (xN / xD) = xN / xD
Мы даже можем исключить деление, умножив обе части на последний член:
aD aN aN
y × xD = xN
Теперь это выглядит многообещающе! Функция, которую мы получаем из этого,
aD aN aN
f(y) = y xD - xN
Метод Ньютона также требует производной, которая, очевидно,
f(y) aD aN
⎼⎼⎼⎼ = df(y) = y xD y / aD
dy
Сам метод Ньютона основан на повторении
f(y)
y = y - ⎼⎼⎼⎼⎼⎼
i+1 i df(y)
Если вы разберетесь с математикой, вы обнаружите, что итерация просто
aD
y[i] y[i] xN
y[i+1] = y[i] - ⎼⎼⎼⎼ + ⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼⎼
aD aD aN
aD y[i] xD
Вам не нужно хранить все значения y в памяти; достаточно запомнить последний и прекратить повторение, когда их разница достаточно мала.
У вас все еще есть возведение в степень выше, но теперь это только целочисленное возведение в степень, т.е.
aD
xN = xN × xN × .. × xN
╰───────┬───────╯
aD times
что вы можете сделать очень просто, например, просто умножив аргумент сам на себя желаемое количество раз, например в C,
double ipow(const double base, const int exponent)
{
double result = 1.0;
int i;
for (i = 0; i < exponent; i++)
result *= base;
return result;
}
Существуют более эффективные методы для выполнения целочисленного возведения в степень, но указанная выше функция должна быть вполне приемлемой для этого.
Последняя проблема - выбрать начальное y, чтобы получить сходимость. Вы не можете использовать 0, потому что (степень) y используется в качестве знаменателя при делении; вы получите деление на нулевую ошибку. Лично я проверял, должен ли результат быть положительным или отрицательным, а также быть меньше или больше единицы по величине; два общих правила, чтобы выбрать безопасное начальное y.
Вопросы?
person
Nominal Animal
schedule
04.07.2014
3.2 = 3^(1/5)
? - person R Sahu   schedule 04.07.2014pow
- очень сложная библиотечная функция (вероятно, самая сложная и непонятная из всех математических библиотечных функций), которую трудно воспроизвести и которая совершенно непрактична в качестве отдельной аппаратной операции. - person R.. GitHub STOP HELPING ICE   schedule 04.07.2014