Здравствуйте!
Столкнулась вот с такой проблемой:
В программе генерируются случайные числа, распределённые по нормальному з-ну. Но суть не совсем в этом.
Когда требуется сгенерировать 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);
}
}
Во-первых, randomize()... Во-вторых, этот самый randomize() в цикле запускать нельзя, только перед началом вычислений, однократно. В третьих, желательно переменную yi сделать ЛОКАЛЬНОЙ:
double xi = 0., xiStar = 0.;и куда делся domain error?
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);
}
}
//---------------------------------------------------------------------------
#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);
}
}
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; // <-- Здесь - то же самое
Ну просто напасть какая-то...Я снова увеличиваю размер генерируемой последовательности (до 60 000 элементов) - и вновь лезут ошибки log10:sign error... И в чём же теперь причина - для меня непостижимо(
Может рандом выдаёт какое-то недопустимое значение аргумента...?
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, и ты попытаешься вычислить квадратный корень из отрицательного числа. Поверь, ни к чему хорошему это не приведет...