Консультация № 180190
07.10.2010, 17:02
41.55 руб.
0 16 1
Здравствуйте.
Прошу еще помощи.

Тестирую свой датчик случайных чисел на независимость.
Для этой проверки использую метод вычисления корреляционных моментов (коэффициента корреляции).
Берутся пары чисел х0 и х1, х1 и х2 и т.д. и вычисляется корреляционный момент:

(1/n) * Σ (xi – 0,5)(xi+1 – 0,5).


У меня имеется на форме Memo1 c вещественными числами:
0,8765
0,2345
0,1245
0,5090
0,1223
0,5656
нужно их сложит по формуле
(1/n) * Σ (xi – 0,5)(xi+1 – 0,5).


У меня получилось сложить только 2 первых числа, этот код расположен в приложении


Приложение:
var
s:real;
i:integer;
begin
s:=0;
with RichEdit1.Lines do
for i := 0 to Count - 1 do
s := strtofloat(Strings[0]) + strtofloat(Strings[1]);

//если так то выдаст ошибку несоответствия типов

s := strtofloat(Strings[0+i]) + strtofloat(Strings[1+i]);

Обсуждение

Неизвестный
07.10.2010, 18:21
общий
novij2011:
Для расчетов надо использовать массивы.
Memo (как и RichEdit) надо использовать только для вывода результатов.
URL >>Проект
Код:

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;

type
Tdata = record // создадим структуру 1 и 2 переменных, будем тут хранить СС
x1:double;
x2:double;
end;
TRandMas = array of Tdata; // этот тип - наш динамический массив


procedure GenRand(var _m:TRandMas; n:integer); // функция генерации СВ
function SolveCor(_m:TRandMas):double; // ваша функция подсчета корреляционный момент
implementation

procedure GenRand(var _m:TRandMas; // массив переменных
n:integer // количество элементов в массиве
); // массив передаем по ссылке, т.е. он измениться в процедуре
var i:integer;
begin
if Length(_m) < n then // если массив меньше требуемого,
SetLength(_m,n); // то установим необходимый размер
for i:= 0 to n-1 do // заполним массив
begin
{вместо random - можно использовать ваш гениратор СВ}
_m[i].x1 := random * 10; // заполняем 1-ю переменную случайным числом
_m[i].x2 := random * 10; // заполняем 2-ю переменную случайным числом
end;
end;

function SolveCor(_m:TRandMas):double;
var i, x:integer;
t:double;
begin
result := 0; //результат = 0
x := Length(_m); // получаем количество элементов в массиве
if(x <= 0) then // если массив пуст
exit; // то ввыходим - считать нечего, результат = 0
for i:= 0 to x-1 do
begin
t := (_m[i].x2 - 0.5); // получаем знаменатель
if(t <> 0) then // если он не = 0 (на 0 делить - будет ошибка)
result := result + (_m[i].x1 - 0.5) / (_m[i].x2 - 0.5); // то делим и суммируем
end;
result := result / x // поделили сумму на количество элементов взяли среднне
end;
end.


модуль формы
Код:
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Edit1: TEdit;
Label1: TLabel;
Label2: TLabel;
procedure Button1Click(Sender: TObject);
private

public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var m:TRandMas; // это переменная на динамический массив
var i:integer;
begin
GenRand(m, StrToIntDef(Edit1.Text,0));
for i:= 0 to Length(m)-1 do
Memo1.Lines.Add(FloatToStrf(m[i].x1,ffNumber,3,2)+' - ' + FloatToStrf(m[i].x2,ffNumber,3,2));
Label2.Caption := Format('корреляционный момент: %.3f',[SolveCor(m)]);
end;

end.



Неизвестный
07.10.2010, 18:35
общий
спасибо, думал будет небольшая программа.
Буду сейчас разбиратьсяв ней.
Неизвестный
07.10.2010, 18:50
общий
а мне получается всместо
Код:
procedure GenRand(var _m:TRandMas; // массив переменных
n:integer // количество элементов в массиве
); // массив передаем по ссылке, т.е. он измениться в процедуре
var i:integer;
begin
if Length(_m) < n then // если массив меньше требуемого,
SetLength(_m,n); // то установим необходимый размер
for i:= 0 to n-1 do // заполним массив
begin
{вместо random - можно использовать ваш гениратор СВ}
_m[i].x1 := random * 10; // заполняем 1-ю переменную случайным числом
_m[i].x2 := random * 10; // заполняем 2-ю переменную случайным числом
end;
end;

нужно подставить первое число в _m[i].x1 а второе в _m[i].x2 , а потом второе число в _m[i].x1 , а третье в _m[i].x2 из memo1, раз там у меня уже храниться массив из 50 вещественных чисел.
У меня же они как раз храняться в memo1 и количество строк 50 там.
Неизвестный
07.10.2010, 19:06
общий
у вас при нажатиии на button1 получается появляются не случайные числа?
0,00 - 0,31
8,61 - 2,03
2,73 - 6,72
3,19 - 1,62
почему то посоянно одинаковые?
например при размере массива =4 я взял
Неизвестный
07.10.2010, 19:13
общий
Цитата: 19206
Memo (как и RichEdit) надо использовать только для вывода результатов.

Richedit я использую и для ввода результатов, вместо random.
Поможите мне реализовать с richedit вместо random?
Неизвестный
07.10.2010, 19:18
общий
Цитата: 324805
Memo (как и RichEdit) надо использовать только для вывода результатов.

Richedit я использую и для ввода результатов, вместо random.
Поможите мне реализовать с richedit вместо random?

вот например, но все равно он приписывает числа к введенным в edit.
Код:
with Form1.memo1.Lines do
for j := 0 to Count - 1 do

_m[i].x1 := strtofloat(Strings[j]); // заполняем 1-ю переменную случайным числом
with Form1.memo1.Lines do
for j := 0 to Count - 1 do
_m[i].x2 := strtofloat(Strings[j]); // заполняем 2-ю переменную случайным числом
Неизвестный
07.10.2010, 19:31
общий
Объясните пожалуйста почему тут цифры одинаковые получаются в memo1 в результате
0,00 - 0,31
8,61 - 2,03
2,73 - 6,72
3,19 - 1,62
всегда одни и те же?
Неизвестный
07.10.2010, 19:38
общий
Объясните пожалуйста почему тут цифры одинаковые получаются в memo1 в результате

Потому что я не инициализирую генератор, потому всегда при новом запуске он повторяет значения.
Имелось ввиду, что вместо random Вы будите использовать свой
Тестирую свой датчик случайных чисел на независимость.
.
Потому использовать Memo тут не надо, только для вывода результата.

У вас есть генератор? Вы же сказали что тестируете свой датчик..
Покажите его, он в виде функции как я понимаю?

Для того, что бы генератор был случайным - надо добавить
Код:

procedure GenRand(var _m:TRandMas; // массив переменных
n:integer // количество элементов в массиве
); // массив передаем по ссылке, т.е. он измениться в процедуре
var i:integer;
begin
randomize;
if Length(_m) < n then // если массив меньше требуемого,
SetLength(_m,n); // то установим необходимый размер
for i:= 0 to n-1 do // заполним массив
begin
{вместо random - можно использовать ваш генератор СВ}
// заполняем 1-ю переменную случайным числом вот тут, вместо random - можно подставлять свой генератор
_m[i].x1 := random * 10;
_m[i].x2 := random * 10; // заполняем 2-ю переменную случайным числом
end;
end;

Неизвестный
07.10.2010, 19:51
общий
это датчик по методу середины квдратов.
Все числа сгенерированные им я записал в Richedit1
Вот поэтому и спросил, потому что я вместо random хочу записать уже сгенерированные числа из richedit.
Неизвестный
07.10.2010, 19:53
общий
novij2011:
Все числа сгенерированные им я записал в Richedit1

Простите, а вы на калькуляторе их получили, эти числа?
Или, всё же программно? Если программно - то покажите код, я подскажу как его использовать.
Если Ваш код очень секретный - то просто оформите генерацию СВ как отдельную функцию - и эту функцию подставите вместо random
потому что я вместо random хочу записать уже сгенерированные числа из richedit.

Вы программируете - есть вещи, на которые ответы даются в виде решения, а не нагромождения ошибок.
Вы учитесь, и понятно что не знаете как надо использовать то или иное - я поясняю - вся логика находится в функции GenRand - это она вам в memo и т.д. вернет массив СВ.
А вот сам генератор - это уже дело хозяйское. Если надо использовать свой, то и [b]используйте вместо random НО ГЕНРАТОР а не значения из Memo.[/b]
Неизвестный
07.10.2010, 19:57
общий
Вот код:
Код:

procedure TForm1.Button1Click(Sender: TObject);//генерация
var
n: real;
i:integer;
a:string;

begin
RichEdit1.Lines.Add(Edit1.Text);
for i:=0 to 50 do
begin

n:=Strtofloat(Edit1.Text)*StrTofloat(Edit1.Text);
Edit2.Text :=floatTostr(n);

a:=(Copy(Trim(Edit2.Text),5,4) );
Edit1.Text:='0,'+a;

RichEdit1.Lines.Add(Edit1.Text);
end;
Неизвестный
07.10.2010, 20:01
общий
0,6863\par
0,1007\par
0,0140\par
0,0196\par
0,0384\par
0,1474\par
0,1726\par
0,9790\par
0,8441\par
0,2504\par
0,2700\par
0,29\par
0,41\par
0,81\par
0,61\par
0,21\par
0,41\par
0,81\par
0,61\par
0,21\par
0,41\par
0,81\par
0,61\par
0,21\par
0,41\par
0,81\par
0,61\par
0,21\par
0,41\par
0,81\par
0,61\par
0,21\par
0,41\par
0,81\par
0,61\par
0,21\par
0,41\par
0,81\par
0,61\par
0,21\par
0,41\par
0,81\par
0,61\par
0,21\par
0,410,81
0,61
0,21
0,41
0,81
0,61

это сгенерированные числа
Неизвестный
07.10.2010, 21:16
общий
Ваша функция - вырождающаяся:
Код:
procedure TForm1.Button2Click(Sender: TObject);
var
n: real;
i:integer;
a:string;

begin
RichEdit1.Lines.Clear;
RichEdit1.Lines.Add(Edit1.Text);
for i:=0 to 50 do
begin
n:=Strtofloat(Edit1.Text)*StrTofloat(Edit1.Text);
{ n = x * x -> это стермится к нулю, т.к.}
Edit2.Text :=floatTostr(n);
{несмотря на то, что берете только 4 цифры, с каждой итерацией порядок уменьшается
т.е. число становится меньше: 0,1 * 0,1 = 0,01 -> 0.01*0.01 = 0,0001 и т.д.
на определенном этапе, эти 4 числа будут = 0 т.е. результат стремится к нулю.}
a:=(Copy(Trim(Edit2.Text),Length(Edit2.Text) div 2,Length(Edit2.Text)) );
Edit1.Text:='0,'+a;
RichEdit1.Lines.Add(Edit1.Text);
end;
end;


вот с учетом ваших требований.. (алгоритм сохранен, только теперь он работает правильно)
Код:

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;

type
Tdata = record // создадим структуру 1 и 2 переменных, будем тут хранить СС
x1:double;
x2:double;
end;
TRandMas = array of Tdata; // этот тип - наш динамический массив


procedure GenRand(var _m:TRandMas; x:double; n:integer); // функция генерации СВ
function SolveCor(_m:TRandMas):double; // ваша функция подсчета корреляционный момент
implementation
//*************** ВАШ ГЕНЕРАТОР ************************************************
procedure MyRand(_m:TRandMas; x:double; count:integer);
var
n: double;
i,k:integer;
s:string;

begin
k := count div 2;
if Length(_m) < k then
SetLength(_m,k);
n:=x*x;
for i:=0 to k-1 do
begin
s := FloatTostr(n);
Delete(s,1, Pos(',',s));
s:= IntToStr(StrToInt(Copy(s, Length(s) div 2, 4))); // тут меленькая хитрость - что бы избавиться от возможных ведущих нулей, преобразуем к integer потом в строку..
_m[i].x1:=StrToFloatDef('0,'+ s,0);
n:=_m[i].x1*_m[i].x1;
s :=FloatToStr(n);
Delete(s,1, Pos(',',s));
s:= IntToStr(StrToInt(Copy(s, Length(s) div 2, 4)));
_m[i].x2:=StrToFloatDef('0,'+s,0);
n:=_m[i].x2*_m[i].x2;
end;
end;
//******************************************************************************
procedure GenRand(var _m:TRandMas; // массив переменных
x:double; // начальное число
n:integer // количество элементов в массиве
); // массив передаем по ссылке, т.е. он измениться в процедуре
var i:integer;
begin
randomize;
if Length(_m) < n then // если массив меньше требуемого,
SetLength(_m,n); // то установим необходимый размер
MyRand(_m, x, n);
end;
//******************************************************************************
function SolveCor(_m:TRandMas):double;
var i, x:integer;
t:double;
begin
result := 0; //результат = 0
x := Length(_m); // получаем количество элементов в массиве
if(x <= 0) then // если массив пуст
exit; // то ввыходим - считать нечего, результат = 0
for i:= 0 to x-1 do
begin
t := (_m[i].x2 - 0.5); // получаем знаменатель
if(t <> 0) then // если он не = 0 (на 0 делить - будет ошибка)
result := result + (_m[i].x1 - 0.5) / (_m[i].x2 - 0.5); // то делим и суммируем
end;
result := result / x // поделили сумму на количество элементов взяли среднне
end;
//******************************************************************************

end.



модуль формы
Код:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls;

type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Edit1: TEdit;
Label1: TLabel;
Label2: TLabel;
RichEdit1: TRichEdit;
Button2: TButton;
Edit2: TEdit;
Label3: TLabel;
procedure Button1Click(Sender: TObject);
private

public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var m:TRandMas; // это переменная на динамический массив
var i:integer;
begin
Memo1.Lines.Clear;
GenRand(m, StrToFloatDef(Edit2.Text,0), StrToIntDef(Edit1.Text,0));
for i:= 0 to (Length(m) div 2)-1 do
Memo1.Lines.Add(Format('%-4d: %.4f - %.4f',[i,m[i].x1,m[i].x2]));
Label2.Caption := Format('корреляционный момент: %.3f',[SolveCor(m)]);
end;
end.

приложение:URL >>Проект
Неизвестный
07.10.2010, 21:26
общий
novij2011:
А вообще, как правило используют для первичной генерации – текущее время..
замените вызов функции как показано ниже, а Edit2 можно вообще не использовать
Код:

procedure TForm1.Button1Click(Sender: TObject);
var m:TRandMas; // это переменная на динамический массив
i:integer;
begin
Memo1.Lines.Clear;
GenRand(m, now, StrToIntDef(Edit1.Text,0));
for i:= 0 to (Length(m) div 2)-1 do
Memo1.Lines.Add(Format('%-4d: %.4f - %.4f',[i,m[i].x1,m[i].x2]));
Label2.Caption := Format('корреляционный момент: %.3f',[SolveCor(m)]);
end;

Неизвестный
07.10.2010, 21:57
общий
спасибо
Неизвестный
08.10.2010, 15:51
общий
это ответ
Здравствуйте, novij2011.

По просьбе Victor Pyrlik, добавляю его ответ (после большого обсуждения в минифоруме):

novij2011 Ваша функция - вырождающаяся:

Код:

procedure TForm1.Button2Click(Sender: TObject);
var
n: real;
i:integer;
a:string;

begin
RichEdit1.Lines.Clear;
RichEdit1.Lines.Add(Edit1.Text);
for i:=0 to 50 do
begin
n:=Strtofloat(Edit1.Text)*StrTofloat(Edit1.Text);
{ n = x * x -> это стермится к нулю, т.к.}
Edit2.Text :=floatTostr(n);
{несмотря на то, что берете только 4 цифры, с каждой итерацией порядок уменьшается
т.е. число становится меньше: 0,1 * 0,1 = 0,01 -> 0.01*0.01 = 0,0001 и т.д.
на определенном этапе, эти 4 числа будут = 0 т.е. результат стремится к нулю.}
a:=(Copy(Trim(Edit2.Text),Length(Edit2.Text) div 2,Length(Edit2.Text)) );
Edit1.Text:='0,'+a;
RichEdit1.Lines.Add(Edit1.Text);
end;
end;


С учетом Ваших требований... решение Вашей задачи:
Код:

unit Unit2;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;

type
Tdata = record // создадим структуру 1 и 2 переменных, будем тут хранить СС
x1:double;
x2:double;
end;
TRandMas = array of Tdata; // этот тип - наш динамический массив


procedure GenRand(var _m:TRandMas; x:double; n:integer); // функция генерации СВ
function SolveCor(_m:TRandMas):double; // ваша функция подсчета корреляционный момент
implementation
//*************** ВАШ ГЕНЕРАТОР ************************************************
procedure MyRand(_m:TRandMas; x:double; count:integer);
var
n: double;
i,k:integer;
s:string;

begin
k := count div 2;
if Length(_m) < k then
SetLength(_m,k);
n:=x*x;
for i:=0 to k-1 do
begin
s := FloatTostr(n);
Delete(s,1, Pos(',',s));
s:= IntToStr(StrToInt(Copy(s, Length(s) div 2, 4))); // тут меленькая хитрость - что бы избавиться от возможных ведущих нулей, преобразуем к integer потом в строку..
_m[i].x1:=StrToFloatDef('0,'+ s,0);
n:=_m[i].x1*_m[i].x1;
s :=FloatToStr(n);
Delete(s,1, Pos(',',s));
s:= IntToStr(StrToInt(Copy(s, Length(s) div 2, 4)));
_m[i].x2:=StrToFloatDef('0,'+s,0);
n:=_m[i].x2*_m[i].x2;
end;
end;
//******************************************************************************
procedure GenRand(var _m:TRandMas; // массив переменных
x:double; // начальное число
n:integer // количество элементов в массиве
); // массив передаем по ссылке, т.е. он измениться в процедуре
var i:integer;
begin
randomize;
if Length(_m) < n then // если массив меньше требуемого,
SetLength(_m,n); // то установим необходимый размер
MyRand(_m, x, n);
end;
//******************************************************************************
function SolveCor(_m:TRandMas):double;
var i, x:integer;
t:double;
begin
result := 0; //результат = 0
x := Length(_m); // получаем количество элементов в массиве
if(x <= 0) then // если массив пуст
exit; // то ввыходим - считать нечего, результат = 0
for i:= 0 to x-1 do
begin
t := (_m[i].x2 - 0.5); // получаем знаменатель
if(t <> 0) then // если он не = 0 (на 0 делить - будет ошибка)
result := result + (_m[i].x1 - 0.5) / (_m[i].x2 - 0.5); // то делим и суммируем
end;
result := result / x // поделили сумму на количество элементов взяли среднне
end;
//******************************************************************************

end.



модуль формы:

Код:

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls;

type
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Edit1: TEdit;
Label1: TLabel;
Label2: TLabel;
RichEdit1: TRichEdit;
Button2: TButton;
Edit2: TEdit;
Label3: TLabel;
procedure Button1Click(Sender: TObject);
private

public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses Unit2;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var m:TRandMas; // это переменная на динамический массив
var i:integer;
begin
Memo1.Lines.Clear;
GenRand(m, StrToFloatDef(Edit2.Text,0), StrToIntDef(Edit1.Text,0));
for i:= 0 to (Length(m) div 2)-1 do
Memo1.Lines.Add(Format('%-4d: %.4f - %.4f',[i,m[i].x1,m[i].x2]));
Label2.Caption := Format('корреляционный момент: %.3f',[SolveCor(m)]);
end;
end.


А вообще, как правило используют для первичной генерации – текущее время..
замените вызов функции как показано ниже, а Edit2 можно вообще не использовать :

Код:

procedure TForm1.Button1Click(Sender: TObject);
var m:TRandMas; // это переменная на динамический массив
i:integer;
begin
Memo1.Lines.Clear;
GenRand(m, now, StrToIntDef(Edit1.Text,0));
for i:= 0 to (Length(m) div 2)-1 do
Memo1.Lines.Add(Format('%-4d: %.4f - %.4f',[i,m[i].x1,m[i].x2]));
Label2.Caption := Format('корреляционный момент: %.3f',[SolveCor(m)]);
end;


Вы можете cкачать программу (с исходниками) на Delphi.
Форма ответа