Помощь - Поиск - Пользователи - Календарь
Полная версия: [С++ Builder 6] pow: domain error
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
18192123
Здравствуйте!

Столкнулась вот с такой проблемой:
В программе генерируются случайные числа, распределённые по нормальному з-ну. Но суть не совсем в этом.
Когда требуется сгенерировать 500-1000 значений - всё нормально, когда же я захотела получить 10 000 значений - ошибка pow: DOMAIN error..

double xi = 0, xiStar = 0, yi = 0;
float sigma1 = 1, sigma3 = 1;
float m1 = 5, m3 = 3;
..............
double GaussLow(int var)
{
randomize;
xi = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
xiStar = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
switch (var)
{
case 1:
yi = sigma1 * cos(2*M_PI*xi) * pow(-2*log10(xiStar),1/2) + m1;
break;
case 2:
yi = sigma3 * cos(2*M_PI*xi) * pow(-2*log10(xiStar),1/2) + m3;
}
return yi;
}
............
void __fastcall TForm2MS::ButGenClick(TObject *Sender)
{
double tempG = 0;
int test = 10000;
StrGrGen->RowCount = test+1;
StrGrGen->Visible = true;
StrGrGen->Cells[1][0] = "Íîðìàëüíûé ç-í";
StrGrGen->Cells[2][0] = "Íîðìàëüíûé ç-í";
for (int i=0;i<test;i++)
{
StrGrGen->Cells[0][i+1] = i+1;
tempG = GaussLow(1);
StrGrGen->Cells[1][i+1] = FloatToStrF(tempG,ffFixed,8,5);
tempG = 0;
tempG = GaussLow(2);
StrGrGen->Cells[2][i+1] = FloatToStrF(tempG,ffFixed,8,5);
}
}


Объясните пожалуйста, в чём тут дело? Как избежать ошибки..?
Подозреваю, что проблема можеть быть связана с областями определения (значения) pow или log10..
volvo
Во-первых, randomize()... Во-вторых, этот самый randomize() в цикле запускать нельзя, только перед началом вычислений, однократно. В третьих, желательно переменную yi сделать ЛОКАЛЬНОЙ:
double xi = 0., xiStar = 0.;
double sigma1 = 1., sigma3 = 1.;
double m1 = 5., m3 = 3.;

double GaussLow(int var)
{
double yi; // Три
xi = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
xiStar = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
switch (var)
{
case 1:
yi = sigma1 * cos(2*M_PI*xi) * pow(-2*log10(xiStar),1/2) + m1;
break;
case 2:
yi = sigma3 * cos(2*M_PI*xi) * pow(-2*log10(xiStar),1/2) + m3;
}
return yi;
}
void __fastcall TForm2MS::ButGenClick(TObject *Sender)
{
// раз, два
randomize();

double tempG = 0;
int test = 10000;

StrGrGen->RowCount = test+1;
StrGrGen->Visible = true;
StrGrGen->Cells[1][0] = "Íîðìàëüíûé ç-í";
StrGrGen->Cells[2][0] = "Íîðìàëüíûé ç-í";
for (int i=0;i<test;i++)
{
StrGrGen->Cells[0][i+1] = i+1;
tempG = GaussLow(1);
StrGrGen->Cells[1][i+1] = FloatToStrF(tempG,ffFixed,8,5);
tempG = 0;
tempG = GaussLow(2);
StrGrGen->Cells[2][i+1] = FloatToStrF(tempG,ffFixed,8,5);
}
}
и куда делся domain error? smile.gif
18192123
Цитата(volvo @ 18.10.2009 17:35) *

и куда делся domain error? smile.gif


я добавила ещё одну ф-ю EXpLow для генерации чисел, распределённых по экспоненциальному з-ну..
внесла изменения относительно randomize..
Запустила - отработало без ошибок!
Запустила снова - тут вам кроме pow: DOMAIN error, и log10: SING error, и pow: OVERFLOW error..

Вот как-то так.. blink.gif

//---------------------------------------------------------------------------

#include <vcl.h>
#include <math.h>
#pragma hdrstop

#include <utilcls.h>
#include <sysvari.h>
#include <ComObj.hpp>

#include "UnitMain.h"
#include "Unit_Stochastic_variables.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2MS *Form2MS;

//my description
double xi = 0., xiStar = 0.;
double sigma1 = 1., sigma3 = 1.;
double m1 = 5., m3 = 3.;
double lambda2 = 0.16;
//---------------------------------------------------------------------------
__fastcall TForm2MS::TForm2MS(TComponent* Owner)
: TForm(Owner)
{

}
//---------------------------------------------------------------------------
double GaussLow(int var)
{
double yi;
xi = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
xiStar = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
switch (var)
{
case 1:
yi = sigma1 * cos(2*M_PI*xi) * pow(-2*log10(xiStar),1/2) + m1;
break;
case 2:
yi = sigma3 * cos(2*M_PI*xi) * pow(-2*log10(xiStar),1/2) + m3;
}
return yi;
}
//---------------------------------------------------------------------------
double ExpLow()
{
double yi;
xi = static_cast<double>(rand()) / static_cast<double>(RAND_MAX);
yi = (-1/lambda2) * log10(xi);
return yi;
}

void __fastcall TForm2MS::ButGenClick(TObject *Sender)
{
randomize();
double tempG = 0, tempE = 0;
int test = 10000;
StrGrGen->RowCount = test+1;
StrGrGen->Visible = true;
StrGrGen->Cells[1][0] = "Нормальный з-н";
StrGrGen->Cells[2][0] = "Нормальный з-н";
StrGrGen->Cells[3][0] = "Показательный з-н";
for (int i=0;i<test;i++)
{
StrGrGen->Cells[0][i+1] = i+1;
tempG = GaussLow(1);
StrGrGen->Cells[1][i+1] = FloatToStrF(tempG,ffFixed,8,5);
tempG = 0;
tempG = GaussLow(2);
StrGrGen->Cells[2][i+1] = FloatToStrF(tempG,ffFixed,8,5);
tempE = ExpLow();
StrGrGen->Cells[3][i+1] = FloatToStrF(tempE,ffFixed,8,5);
}
}



volvo
case 1:
yi = sigma1 * cos(2*M_PI*xi) * pow(-2*log10(xiStar),1./2.) + m1; // <-- 1/2 в Сях = 0, тебе надо 1.0/2.0
break;
case 2:
yi = sigma3 * cos(2*M_PI*xi) * pow(-2*log10(xiStar),1./2.) + m3; // <-- Здесь - то же самое
Внимательнее с этими вещами...
18192123
Ну просто напасть какая-то...Я снова увеличиваю размер генерируемой последовательности (до 60 000 элементов) - и вновь лезут ошибки log10:sign error... И в чём же теперь причина - для меня непостижимо(
Может рандом выдаёт какое-то недопустимое значение аргумента...?
volvo
Цитата
Может рандом выдаёт какое-то недопустимое значение аргумента...?
Вполне возможно... Я тебе даже скажу какое значение должно выдаваться, чтобы ты получала то, что получаешь: НОЛЬ... Если rand() вернул 0, то xiStar (естественно) тоже будет = 0, а это некорректные входные данные, это оговорено в описании функции. Так что придется тебе гарантировать, что аргумент log10 не будет нулевым. Ну, например, так:
int sure_rand()
{
int rnd = rand();

if(!rnd) rnd += 1;
return rnd;
}
...
xiStar = static_cast<double>(sure_rand()) / static_cast<double>(RAND_MAX);


Если сделать просто:
xiStar = static_cast<double>(rand() + 1) / static_cast<double>(RAND_MAX);
, то получишь сбой, когда rand() вернет RAND_MAX... Тогда xiStar примет значение > 1, следовательно log10(xiStar) станет больше 0, и ты попытаешься вычислить квадратный корень из отрицательного числа. Поверь, ни к чему хорошему это не приведет...
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.