Форум программистов, компьютерный форум CyberForum.ru

Функция возведения в степень - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.64
OasisKharkov
1 / 1 / 0
Регистрация: 28.07.2012
Сообщений: 35
18.11.2012, 21:01     Функция возведения в степень #1
Добрый день.
Ребята, помогите решить проблему.
Написал функцию для вычисления действительных корней кубического уравнения.
возникает непонятная ситуация в случае, когда дискриминант D > 0.
При извлечении корня третей степени, для нахождения коэффициентов, функция pow() в случае, когда основание
отрицательно, выдает какое-то левое число... ведь вроде и в основании и в показателе степени может содержаться любое число, как положительное, так и отрицательное, лишь бы оно было формата double:
double pow (double x, double y).

Вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
void qubic(void){
    double a, b, c, d;
    double r, s, t;
    double p, q, D;
    double ro, fi;
    double u, v;
    double x1, x2, x3;
    const double pi = 3.14159265;
    const double pw = 0.33333333;
 
    cout << "Введите коэффициент a: ";
    cin >> a;
    cout << "Введите коэффициент b: ";
    cin >> b;
    cout << "Введите коэффициент c: ";
    cin >> c;
    cout << "Введите коэффициент d: ";
    cin >> d;
    cout << "\n";
    
    r = b/a;
    s = c/a;
    t = d/a;
 
    p = s - r*r/3;
    q = 2*pow(r,3)/27 - r*s/3 + t;
    D = pow((p/3),3) + pow((q/2),2);
    cout << D << "\n";
    cout << p << "\n";
    cout << q << "\n";
    cout << r << "\n";
    if (D<0){
        ro = sqrt(-pow(p,3)/27);
        fi = acos(-q/(2*p));
        
        x1 = 2*pow(ro,pw)*cos(fi/3) - r/3;
        x2 = 2*pow(ro,pw)*cos(fi/3 + 2*pi/3) - r/3;
        x3 = 2*pow(ro,pw)*cos(fi/3 + 4*pi/3) - r/3;
 
        cout << "Корни уравнения: " << x1 << ", " << x2 << " и " << x3 << "\n";
    }
    else{
        u = pow(-q/2+sqrt(D),pw);
        cout << u << "\n";
        v = pow(-q/2-sqrt(D),pw);
        cout << v << "\n";
        
        cout << pow (-10.0, 0.3);       
        x1 = u + v - r/3;
 
        cout << "Корень уравнения: " << x1 << "\n";
    }
    return;
}
Собственно, я даже строку указал
C++
1
cout << pow (-10.0, 0.3);
- которая тоже каракули выдает, неужели основание должно быть строго положительно?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Peregrin
33 / 33 / 1
Регистрация: 16.11.2012
Сообщений: 59
19.11.2012, 03:39     Функция возведения в степень #2
http://devoid.com.ua/functions-about...tions/pow.html
double pow(double x, double y)
Если x отрицательное, а y не является целой, функция печатает сообщение об ошибке DOMAIN в stderr, устанавливает errno в ERANGE и возвращает либо положительное, либо отрицательное значение HUGE.
OasisKharkov
1 / 1 / 0
Регистрация: 28.07.2012
Сообщений: 35
19.11.2012, 13:19  [ТС]     Функция возведения в степень #3
Что же теперь делать? Может имеется какая-то альтернативная функция?
Видел реализацию этого алгоритма на паскале, там же работает...
И насколько я понял в данном случае, например pow(x,y), аргумент 'y' нельзя поставить в виде выражения, например указать типа 1/3 - корень третей степени, я вышел из ситуации, подставив в формулу константное значение pw = 0.333333, насколько это корректно?
Peregrin
33 / 33 / 1
Регистрация: 16.11.2012
Сообщений: 59
19.11.2012, 14:13     Функция возведения в степень #4
А почему просто не воспользоваться тем, что (-x)1/3 == -(x)1/3? И возводить положительный х в степень 1/3.
OasisKharkov
1 / 1 / 0
Регистрация: 28.07.2012
Сообщений: 35
19.11.2012, 14:31  [ТС]     Функция возведения в степень #5
Я это учитывал! тут не все так просто, если я вынесу минус из под знака корня, это поможет лишь в одном случае...
\sqrt[3]{-q/2+\sqrt{D}}
\sqrt[3]{-q/2-\sqrt{D}}
Для второго корня это сработает... а в первом случае, хоть выноси, хоть не выноси, под корнем разность двух значений, и это значение не всегда будет положительно. Тем более q/2 может быть меньше значения дискриминанта, к тому же, оно очень часто получается отрицательным...
Peregrin
33 / 33 / 1
Регистрация: 16.11.2012
Сообщений: 59
19.11.2012, 14:36     Функция возведения в степень #6
Первая идея, что приходит это проверять знак этого выражения и в зависимости от знака вычислять по-разному, что-то типа:
C++
1
u = (-q/2+sqrt(D) > 0 ? 1 : -1) * pow(abs(-q/2+sqrt(D)), pw);
Возможно, есть более лаконичные способы.
OasisKharkov
1 / 1 / 0
Регистрация: 28.07.2012
Сообщений: 35
19.11.2012, 15:42  [ТС]     Функция возведения в степень #7
А вот это уже выход с тернарным оператором, спасибо большое, не додумался бы!

Добавлено через 32 минуты
Теперь надо с этим куском кода разобраться, вроде формулы ввел правильно, но программа считает неверно!
C++
1
2
3
4
5
6
7
8
9
10
 if (D<0){
        ro = sqrt(-pow(p,3)/27);
        fi = acos(-q/(2*p));
        
        x1 = 2*pow(ro,pw)*cos(fi/3) - r/3;
        x2 = 2*pow(ro,pw)*cos(fi/3 + 2*pi/3) - r/3;
        x3 = 2*pow(ro,pw)*cos(fi/3 + 4*pi/3) - r/3;
 
        cout << "Корни уравнения: " << x1 << ", " << x2 << " и " << x3 << "\n";
    }
Очевидно, какая-то функция некорректно работает... может косинус или арккосинус не принимают аргументы в в виде выражений или отрицательные...
Peregrin
33 / 33 / 1
Регистрация: 16.11.2012
Сообщений: 59
19.11.2012, 15:49     Функция возведения в степень #8
Проверьте, везде ли правильно формулы записаны. Каким методом корни рассчитываются?
OasisKharkov
1 / 1 / 0
Регистрация: 28.07.2012
Сообщений: 35
19.11.2012, 15:50  [ТС]     Функция возведения в степень #9
Кстати, небольшая поправочка, надо использовать функции fabs(), а не abs(), так как мы передаем аргумент вещественного типа, а не целого!
Peregrin
33 / 33 / 1
Регистрация: 16.11.2012
Сообщений: 59
19.11.2012, 15:54     Функция возведения в степень #10
Да, точно, там нужен fabs
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.11.2012, 16:05     Функция возведения в степень
Еще ссылки по теме:

C++ Возведения в степень
C++ Функция возведения в степень.
Рекурсивная функция возведения в степень C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
OasisKharkov
1 / 1 / 0
Регистрация: 28.07.2012
Сообщений: 35
19.11.2012, 16:05  [ТС]     Функция возведения в степень #11
Проблему решил, я неправильно записал формулу, вместо коэффициента Ро, подставил коэффициент р... в этом месте:
C++
1
fi = acos(-q/(2*p));
а надо так:
C++
1
fi = acos(-q/(2*ro));
Решал задачу методом Кардано.

Вроде пока вопросы исчерпаны, спасибо Peregrin

Может кому надо, для нахождения действительных корней кубического уравнения, код функции:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
void qubic(void){
    double a, b, c, d;
    double r, s, t;
    double p, q, D;
    double ro, fi;
    double u, v;
    double x1, x2, x3;
    const double pi = 3.14159265;
    const double pw = 0.33333333;
 
    cout << "Введите коэффициент a: ";
    cin >> a;
    cout << "Введите коэффициент b: ";
    cin >> b;
    cout << "Введите коэффициент c: ";
    cin >> c;
    cout << "Введите коэффициент d: ";
    cin >> d;
    cout << "\n";
    
    r = b/a;
    s = c/a;
    t = d/a;
 
    p = s - r*r/3;
    q = 2*pow(r,3)/27 - r*s/3 + t;
    D = pow((p/3),3) + pow((q/2),2);
    
    if (D<0){
        ro = sqrt(-pow(p,3)/27);
        fi = acos(-q/(2*ro));
        
        x1 = 2*pow(ro,pw)*cos(fi/3) - r/3;
        x2 = 2*pow(ro,pw)*cos(fi/3 + 2*pi/3) - r/3;
        x3 = 2*pow(ro,pw)*cos(fi/3 + 4*pi/3) - r/3;
 
        cout << "Корни уравнения: " << x1 << ", " << x2 << " и " << x3 << "\n";
    }
    else{
        u = (-q/2+sqrt(D) > 0 ? 1 : -1) * pow(fabs(-q/2+sqrt(D)),pw);
        v = (-q/2-sqrt(D) > 0 ? 1 : -1) * pow(fabs(-q/2-sqrt(D)),pw);
                    
        x1 = u + v - r/3;
 
        cout << "Корень уравнения: " << x1 << "\n";
    }
    return;
}
Yandex
Объявления
19.11.2012, 16:05     Функция возведения в степень
Ответ Создать тему
Опции темы

Текущее время: 11:15. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru