Форум: Форум C++Разное
Новые темы: 00
PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум C++

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: функция возведение в дробную степень
 
 автор: Cena   (11.12.2011 в 01:51)   письмо автору
 
 

Помогите пожалуйста с кодом, дело в том что, у меня при выполнении программы, функция pow некорректно считает отрицательные значения, то есть:
#include <iostream>
#include <math.h>
using namespace std;
int main()
{double x, xn, xk, dx, a, max, min;
long double z;
int k;
cout<<"xn="; \\xn=1.5\\
cin>>xn;
cout<<"xk="; \\xk=5.5\\
cin>>xk;
cout<<"dx="; \\dx=0.2\\
cin>>dx;
cout<<"a="; \\a=2.94\\
cin>>a;
for(x = xn, k=0; x <= xk; x += dx,k++)
{z=pow(tan(a - x)/(4.35 + sin(a + x)), double(1.0/3.0));
if(k%4==0) cout<<"x="<<x<<"\t z="<<z<<endl;}
if(k==1)
{max=fabs(z);
min=fabs(z);}
if(fabs(z)>max) max=fabs(z);
if(fabs(z)<max) min=fabs(z);
x=x+dx;
cout<<"max="<<max<<"\t min="<<min<<"\n";
cout<<"R="<<max-min<<"\n";
system("PAUSE");
return 0;}
z выдает ошибку, когда нужно возвести отрицательное число в кубический корень, подскажите, как сделать так, чтобы pow считала отрицательные значения?

  Ответить  
 
 автор: cheops   (11.12.2011 в 02:14)   письмо автору
 
   для: Cena   (11.12.2011 в 01:51)
 

В дробную степень можно возвести только целые числа, отрицательные нельзя (в рамках действительных чисел, при при таком возведении чисел получаются комплексные значения).

  Ответить  
 
 автор: Cena   (11.12.2011 в 15:11)   письмо автору
 
   для: cheops   (11.12.2011 в 02:14)
 

Может я не прав, но комплексные числа- это те числа, которые имеют отрицательное значение под корнем и четным показатель степени корня, к примеру, sqrt(-1), или pow(-4, 1./4.), а в данной задаче у меня нечетный показатель степени (кубический), и вручную отрицательное значение извлекается, но в данной ситуации у меня функция pow не справляется с отрицательным значением, а вещественное число отрицательное из кубического корня извлекается.

  Ответить  
 
 автор: cheops   (11.12.2011 в 16:03)   письмо автору
 
   для: Cena   (11.12.2011 в 15:11)
 

>а в данной задаче у меня нечетный показатель степени (кубический)
Я как раз дробный показатель вижу
z = pow(tan(a - x)/(4.35 + sin(a + x)), double(1.0/3.0))
Это означает
z = pow(-X, 1/3)
или другими словами
z = pow(-X, 0.33333333)
вот если double(1.0/3.0) заменить на 3, будет куб и отрицательные числа будут спокойно в него возводиться.

  Ответить  
 
 автор: Cena   (11.12.2011 в 16:24)   письмо автору
 
   для: cheops   (11.12.2011 в 16:03)
 

Подскажите пожалуйста, а как тогда правильно возвести в куб? А насчет вот этой строчки z = pow(-X, 0.33333333) я Вас понял.

  Ответить  
 
 автор: cheops   (11.12.2011 в 16:26)   письмо автору
 
   для: Cena   (11.12.2011 в 16:24)
 

Тогда нужно строку
z = pow(tan(a - x)/(4.35 + sin(a + x)), double(1.0/3.0));
заменить на
z = pow(tan(a - x)/(4.35 + sin(a + x)), 3.0);

  Ответить  
 
 автор: Cena   (11.12.2011 в 16:30)   письмо автору
 
   для: cheops   (11.12.2011 в 16:26)
 

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

  Ответить  
 
 автор: cheops   (11.12.2011 в 17:11)   письмо автору
 
   для: Cena   (11.12.2011 в 16:30)
 

Возьмите Windows-калькулятор и при помощи опции x^y возведите 4^0.5 - это эквивалентно корню квадратному из 4, получается 2. Теперь возведите 27^0.333333333333333333333333333333 (что приближенно эквивалентно кубическому корню), получите 2.9999999999999999999999999999967 т.е. почти 3 (3*3*3 = 27), а теперь подставьте в любую из позиций отрицательное число и получите "Не допустимый аргумент функции". Я понимаю, что вы хотите сказать, что -3 * -3 * -3 = -27, это квадратный корень с отрицательным аргументом уходит в комплексные числа, а кубический - нет и если использовать дроби, а не числа с плавающей точкой, то для ряда отрицательных корней все должно работать. Однако, в императивных языках программирования и вообще в процессоре и его сопроцессоре, как правило, нет дробей. Это удел компьютерных алгебр и символьных языков программирования. Даже если мы сейчас с вами решим эту проблему для целых чисел схожим образом (вообще это возможно), у вас же первый аргумент все равно не целый... т.е. нет такого числа, умножив которое друг на друга три раза можно его получить.

  Ответить  
 
 автор: Cena   (11.12.2011 в 17:17)   письмо автору
 
   для: cheops   (11.12.2011 в 17:11)
 

Большое спасибо за информацию

  Ответить  
 
 автор: cheops   (11.12.2011 в 17:27)   письмо автору
 
   для: Cena   (11.12.2011 в 17:17)
 

Вообще извернуться, конечно, можно - если уверены в том, что делаете, то нужно просто решить оптимизационную задачу s * s * s = tan(a - x)/(4.35 + sin(a + x)), изменяя s таким образом, чтобы тройное произведение наиболее близко было к значению справа (это не совсем корректно с алгебраической точки зрения, но зато задача будет решена, по крайней мере будет вариант). Если уверены, что эта задача должна решаться так, можем попробовать, но у меня ощущение, что мы через стену пытаемся пройти в соседнюю комнату, а где-то должна быть вполне обычная дверь :))), хотя я не буду возражать против похода и через стену :).

  Ответить  
 
 автор: Cena   (11.12.2011 в 17:43)   письмо автору
 
   для: cheops   (11.12.2011 в 17:27)
 

Вы правы был путь очень-очень простой, есть такая функция возведения в кубический корень:
cbrt(x)
#include <iostream>
#include <math.h>
#include <cmath>
using namespace std;
int main()
{
double x,xn,xk,dx,a,max,min;
long double z;
int k;
cout<<"xn=";
cin>>xn;
cout<<"xk=";
cin>>xk;
cout<<"dx=";
cin>>dx;
cout<<"a=";
cin>>a;
for(x = xn, k=0; x <= xk; x += dx,k++)
{
z=cbrt((tan(a - x))/(4.35 + sin(a + x)));
if(k%4==0) cout<<"x="<<x<<"\t z="<<z<<endl;
}
if(k==1)
{
max=z;
min=z;
}
if(z>max) max=z;
if(z<max) min=z;
cout<<"max="<<max<<"\t min="<<min<<"\n";
cout<<"R="<<max-min<<"\n";
system("PAUSE");
return 0;
}
но есть проблема небольшая, у меня min и max после выполнения дают значения, которые вообще не имеет значение z, может я неправильно поставил где-то фигурные скобки?

  Ответить  
 
 автор: cheops   (11.12.2011 в 18:57)   письмо автору
 
   для: Cena   (11.12.2011 в 17:43)
 

Эту задачу лучше решать в отдельной функции, она потребует своего собственного цикла. Такие задачи решаются оптимизационными алгоритмами, т.е. вы приходите к решению последовательно. Берете произвольное начальное значение числа и помножаете его на себя три раза, сравнивая с результатом - не подходит, прибавляете к исходному произвольному числу небольшое значение (варьируете число), повторяете процедуру, опять не подходит, смотрите разницу между исходным числом и результатами. Если после прибавления результат получился еще дальше от исходного числа - вы идете не в ту сторону, если результат ближе, значит вы на верном пути, нужно еще увеличить значение. Повторяя эти операции вы все ближе и ближе будете подходить к тому, что умножение вашего числа три раза на себя будет приближаться к нужному вам результату, чтобы его не проскочить, вам нужно будет уменьшать варьируемое значение, пока оно не станет совсем маленьким, а получаемый результат практически перестанет изменяться и очень близко подойдет к нужному вам числу. Тогда можно прекращать поиск вы получите те самые 2.9999999999999999999999999999967, которые выдает калькулятор и которые очень близки к 3. Этот недостающий хвостик большого значения иметь не будет, так как ошибка, которая накапливается в сопроцессоре еще больше (он многие задачи аналогично решает).
Алогоритмов таких поисков очень много, но все они действуют по указанной выше схеме, только порядок изменения приращения у них разный.

  Ответить  
 
 автор: Cena   (11.12.2011 в 19:30)   письмо автору
 
   для: cheops   (11.12.2011 в 18:57)
 

Спасибо, но функция возведения в кубический корень:
cbrt(x) считает более-менее корректно, но у меня проблема с max и min значениями z, неверные значения z берет за min и max

  Ответить  
 
 автор: cheops   (11.12.2011 в 19:37)   письмо автору
 
   для: Cena   (11.12.2011 в 19:30)
 

Не очень, если очень, понял суть проблемы... у вас в результате получаются неправильные максимальные и минимальные значения?

  Ответить  
 
 автор: Cena   (11.12.2011 в 19:51)   письмо автору
 
   для: cheops   (11.12.2011 в 19:37)
 

Да, у меня неправильно выводятся max и min знвчения в результате выполнения получается:
x=1.5 z=1.3093
x=2.3 z=0.597753
x=3.1 z=-0.33991
x=3.9 z=-0.664024
x=4.7 z=0.99338
max=6.65598e+268 min=0.572952
R=6.65598e+268
некорректно выводит максимальные значения по модулю z, и R (разность) среди max и min

  Ответить  
 
 автор: cheops   (12.12.2011 в 17:04)   письмо автору
 
   для: Cena   (11.12.2011 в 19:51)
 

К сожалению, не могу воспроизвести ситуацию, так как у меня cbrt(x) отсутствует.

  Ответить  
 
 автор: Cena   (13.12.2011 в 23:22)   письмо автору
 
   для: cheops   (12.12.2011 в 17:04)
 

Здраствуйте, подскажите пожалуйста, как организовать цикл по этой программе: do...while?

  Ответить  
 
 автор: cheops   (14.12.2011 в 04:10)   письмо автору
 
   для: Cena   (13.12.2011 в 23:22)
 

Имеется в виду вот этот?
for(x = xn, k=0; x <= xk; x += dx,k++)
{
  z=cbrt((tan(a - x))/(4.35 + sin(a + x)));
  if(k%4==0) cout<<"x="<<x<<"\t z="<<z<<endl;
}
можно поступить следующим образом
x = xn; k=0;
do {
  z=cbrt((tan(a - x))/(4.35 + sin(a + x)));
  if(k%4==0) cout<<"x="<<x<<"\t z="<<z<<endl;
  x += dx; k++;
while (x <= xk;);

  Ответить  
 
 автор: Cena   (14.12.2011 в 18:20)   письмо автору
 
   для: cheops   (14.12.2011 в 04:10)
 

Спасибо

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования