Найти кубический корень в C ++?
Вопрос
Странные вещи случаются, когда я пытаюсь найти кубический корень числа.
Следующий код возвращает меня undefined. В CMD: -1. # Ind
cout<<pow(( double )(20.0*(-3.2) + 30.0),( double )1/3)
Хотя этот этот работает отлично. В CMD: 4.93242414866094
cout<<pow(( double )(20.0*4.5 + 30.0),( double )1/3)
Из математического способа он должен работать, так как мы можем иметь корень куба от отрицательного числа. POW от Visual C ++ 2010 Math.h Библиотека. Есть идеи?
Решение
pow(x, y)
от <cmath>
Не работает, если X отрицательна, а Y не интегральна.
Это ограничение std::pow
, как задокументировано в стандарте C и на CPPreference:
Обработка ошибок
- Ошибки сообщаются, как указано в Math_errandling
- Если база имеет конечное и отрицательное, и EXP - это конечное и не целое число, возникает ошибка домена, и может произойти ошибка диапазона.
- Если база равно нулю, и EXP равен нулю, может возникнуть ошибка домена.
- Если база равно нулю, и EXP отрицателен, может произойти ошибка домена или ошибка полюса.
Вокруг этого ограничения есть пара путей:
Cube-robing такой же, как принять что-то до 1/3 мощности, чтобы вы могли сделать
std::pow(x, 1/3.)
.В C ++ 11 вы можете использовать
std::cbrt
. Отказ C ++ 11 представила функции квадратного корня и Cube-root, но без общего значения N-Th Root-функции преодолевают ограниченияstd::pow
.
Другие советы
Сила 1/3
это особый случай. В общем, неинтегральные полномочия негативных чисел являются сложными. Было бы не было бы практично для принятия специальных случаев, таких как целочисленные корни, и, кроме того, 1/3
Как двойной не ровно 1/3!
Я не знаю о Visual C ++ POW, но страница моего человека говорит по ошибкам:
EDOM
Аргументx
негативно иy
не является неотъемлемой стоимостью. Это приведет к сложному номеру.
Вам придется использовать более специализированные корневые функции Cube, если вы хотите, чтобы кубические корни негативных чисел - или вырезают углы и возьмите абсолютное значение, а затем взять кубик Coot, затем умножьте знак обратно.
Обратите внимание, что в зависимости от контекста, отрицательное число x
к тому 1/3
Мощность не обязательно является отрицательным кубом корень, которые вы ожидаете. Это может быть так же легко быть первым сложным корнем, x^(1/3) * e^(pi*i/3)
. Отказ Это конвенция Mathematica использует; Также разумно просто сказать, что это не определено.
Пока (-1) ^ 3 = -1, вы не можете просто принять рациональную силу отрицательного числа и ожидать реального ответа. Это потому, что есть и другие решения для этого рационального показателя, которые воображаются в природе.
http://www.wolframalpha.com/input/?i=x^(1/3),+x+from+-5+TO+0.
Аналогично, сюжет x ^ x. Для x = -1/3 это должно иметь решение. Однако эта функция считается неопределенной в R для X <0.
Поэтому не ожидайте, что математика.
Угадай, что вы должны взять негативную и положить его впоследствии. Вы можете иметь обертку сделать это для вас, если вы действительно хотите.
function yourPow(double x, double y)
{
if (x < 0)
return -1.0 * pow(-1.0*x, y);
else
return pow(x, y);
}
Не бросайтесь double
используя (double)
, Вместо этого используйте двойную числовую постоянную:
double thingToCubeRoot = -20.*3.2+30;
cout<< thingToCubeRoot/fabs(thingToCubeRoot) * pow( fabs(thingToCubeRoot), 1./3. );
Должен сделать трюк!
Также: не включать <math.h>
в проектах C ++, но использовать <cmath>
вместо.
Альтернативно, использовать pow
из <complex>
Заголовок по причинам, указанным Буддабротом
pow( x, y )
такой же, как (то есть эквивалентный) exp( y * log( x ) )
Если журнал (X) недействителен, то POW (X, Y) также.
Точно так же вы не можете выполнять 0 до мощности чего-либо, хотя математически это должно быть 0.
C ++ 11 имеет cbrt
Функция (см. Например http://en.cppreference.com/w/cpp/numeric/math/cbrt.) так что вы можете написать что-то вроде
#include <iostream>
#include <cmath>
int main(int argc, char* argv[])
{
const double arg = 20.0*(-3.2) + 30.0;
std::cout << cbrt(arg) << "\n";
std::cout << cbrt(-arg) << "\n";
return 0;
}
У меня нет доступа к стандарту C ++, поэтому я не знаю, как обрабатывается негативный аргумент ... тест на IDeOne http://ideone.com/bflxys. Похоже, подтверждает, что C ++ (GCC-4.8.1) расширяет корню куба с этим правилом cbrt(x)=-cbrt(-x)
когда x<0
; Для этого расширения вы можете увидеть http://mathworld.wolfram.com/cuberoot.html.
Я искал Cubit Coot и нашел эту нить, и это происходит для меня, что следующий код может работать:
#include <cmath>
using namespace std;
function double nth-root(double x, double n){
if (!(n%2) || x<0){
throw FAILEXCEPTION(); // even root from negative is fail
}
bool sign = (x >= 0);
x = exp(log(abs(x))/n);
return sign ? x : -x;
}
Я думаю, что вы не должны путать экспоненцию с NTH-ROOT of of of. Увидеть старость Википедия
Потому что 1/3 всегда будет возвращаться 0, так как он будет рассматриваться как целое число ... попробуйте с 1.0 / 3.0 ... Это то, что я думаю, но попробую и реализую ... и не забудьте объявить переменные, содержащие 1,0 и 3.0 Как двойной ...
Вот небольшая функция, которую я постучал.
#define uniform() (rand()/(1.0 + RAND_MAX))
double CBRT(double Z)
{
double guess = Z;
double x, dx;
int loopbreaker;
retry:
x = guess * guess * guess;
loopbreaker = 0;
while (fabs(x - Z) > FLT_EPSILON)
{
dx = 3 * guess*guess;
loopbreaker++;
if (fabs(dx) < DBL_EPSILON || loopbreaker > 53)
{
guess += uniform() * 2 - 1.0;
goto retry;
}
guess -= (x - Z) / dx;
x = guess*guess*guess;
}
return guess;
}
Он использует Ньютон-Рафсон, чтобы найти кубический корень.
Когда-нибудь Ньютон -РАпринсон застрял, если root очень близко к 0, то производное может получить большое, и он может колебаться. Так что я зажал и заставил его перезапустить, если это произойдет. Если вам нужно больше точности, вы можете изменить FLT_EPSILONS.
Если у вас когда-либо не было математической библиотеки, вы можете использовать этот способ для вычисления кубического корня:
кубический корень
double curt(double x) {
if (x == 0) {
// would otherwise return something like 4.257959840008151e-109
return 0;
}
double b = 1; // use any value except 0
double last_b_1 = 0;
double last_b_2 = 0;
while (last_b_1 != b && last_b_2 != b) {
last_b_1 = b;
// use (2 * b + x / b / b) / 3 for small numbers, as suggested by willywonka_dailyblah
b = (b + x / b / b) / 2;
last_b_2 = b;
// use (2 * b + x / b / b) / 3 for small numbers, as suggested by willywonka_dailyblah
b = (b + x / b / b) / 2;
}
return b;
}
Это происходит от sqrt
алгоритм ниже. Идея в том, что b
а также x / b / b
больше и меньше от кубического корня x
. Отказ Итак, среднее значение обеих ближе к кубическому корню x
.
Квадратный корень и кубический корень (в Python)
def sqrt_2(a):
if a == 0:
return 0
b = 1
last_b = 0
while last_b != b:
last_b = b
b = (b + a / b) / 2
return b
def curt_2(a):
if a == 0:
return 0
b = a
last_b_1 = 0;
last_b_2 = 0;
while (last_b_1 != b and last_b_2 != b):
last_b_1 = b;
b = (b + a / b / b) / 2;
last_b_2 = b;
b = (b + a / b / b) / 2;
return b
В отличие от квадратного корня, last_b_1
а также last_b_2
требуются в кубическом корне, потому что B мерцают. Вы можете изменить эти алгоритмы для вычисления четвертого корня, пятого корня и так далее.
Благодаря моим учителю математики Херр Бреннер в 11-м классе, который сказал мне этот алгоритм для sqrt
.
Представление
Я проверил его на Arduino с часовой частотой 16 МГц: