//+------------------------------------------------------------------+
//| 스크립트 프로그램 시작 함수 |
//+------------------------------------------------------------------+
void OnStart()
{
//--- 행렬의 덧셈 및 곱셈 연산
CMatrix A(3),B(3),C();
//--- 행 배열 준비
double a1[3]={1,2,3}, a2[3]={2,3,1}, a3[3]={3,1,2};
double b1[3]={3,2,1}, b2[3]={1,3,2}, b3[3]={2,1,3};
//--- 행렬 채우기
A[0]=a1; A[1]=a2; A[2]=a3;
B[0]=b1; B[1]=b2; B[2]=b3;
//--- Experts 로그에 행렬 출력
Print("---- 행렬 A의 요소");
Print(A.String());
Print("---- 행렬 B의 요소");
Print(B.String());
//--- 행렬의 덧셈
Print("---- 행렬 A와 B의 합");
C=A+B;
//--- 형식 지정된 문자열 표현 출력
Print(C.String());
//--- 행렬의 곱셈
Print("---- 행렬 A와 B의 곱");
C=A*B;
Print(C.String());
//--- 이제 동적 어레이 matrix[i][j] 스타일에서 값을 가져오는 방법을 보여 줍니다.
Print("행렬 C의 값을 요소별로 출력");
//--- 행렬 행(CRow 객체)을 루프로 통과
for(int i=0;i<3;i++)
{
string com="| ";
//--- 행렬에서 값에 대한 행 서식
for(int j=0;j<3;j++)
{
//--- 행과 열의 수로 행렬 요소 가져오기
double element=C[i][j];// [i] - 배열 m_rows[]의 CRow 액세스 ,
// [j] - CRow에서 인덱싱 연산자가 오버로드되었습니다.
com=com+StringFormat("a(%d,%d)=%G ; ",i,j,element);
}
com+="|";
//--- 행의 값을 출력
Print(com);
}
}
//+------------------------------------------------------------------+
//| 클래스 "Row" |
//+------------------------------------------------------------------+
class CRow
{
private:
double m_array[];
public:
//--- 생성자 및 소멸자
CRow(void) { ArrayResize(m_array,0); }
CRow(const CRow &r) { this=r; }
CRow(const double &array[]);
~CRow(void){};
//--- 행의 요소 수
int Size(void) const { return(ArraySize(m_array));}
//--- 값이 포함된 문자열을 반환합니다
string String(void) const;
//--- 인덱싱 연산자
double operator[](int i) const { return(m_array[i]); }
//--- 대입 연산자
void operator=(const double &array[]); // 배열
void operator=(const CRow & r); // 다른 CRow 객체
double operator*(const CRow &o); // 곱셈을 위한 CRow 객체
};
//+------------------------------------------------------------------+
//| 배열을 사용하여 행을 초기화하는 생성자 |
//+------------------------------------------------------------------+
void CRow::CRow(const double &array[])
{
int size=ArraySize(array);
//--- 배열이 비어 있지 않은 경우
if(size>0)
{
ArrayResize(m_array,size);
//--- 값으로 채우기
for(int i=0;i<size;i++)
m_array[i]=array[i];
}
//---
}
//+------------------------------------------------------------------+
//| 배열에 대한 할당 작업 |
//+------------------------------------------------------------------+
void CRow::operator=(const double &array[])
{
int size=ArraySize(array);
if(size==0) return;
//--- 배열을 값으로 채웁니다
ArrayResize(m_array,size);
for(int i=0;i<size;i++) m_array[i]=array[i];
//---
}
//+------------------------------------------------------------------+
//| CRow에 대한 할당 작업 |
//+------------------------------------------------------------------+
void CRow::operator=(const CRow &r)
{
int size=r.Size();
if(size==0) return;
//--- 배열을 값으로 채웁니다
ArrayResize(m_array,size);
for(int i=0;i<size;i++) m_array[i]=r[i];
//---
}
//+------------------------------------------------------------------+
//| 다른 행의 곱셈 연산자 |
//+------------------------------------------------------------------+
double CRow::operator*(const CRow &o)
{
double res=0;
//--- 검증
int size=Size();
if(size!=o.Size() || size==0)
{
Print(__FUNCSIG__,": 두 행렬을 곱하지 못했습니다. 크기가 다릅니다.");
return(res);
}
//--- 요소별로 어레이를 곱하고 결과물 더하기
for(int i=0;i<size;i++)
res+=m_array[i]*o[i];
//--- 결과
return(res);
}
//+------------------------------------------------------------------+
//| 형식이 지정된 문자열 표현을 반환합니다 |
//+------------------------------------------------------------------+
string CRow::String(void) const
{
string out="";
//--- 배열 크기가 0보다 큰 경우
int size=ArraySize(m_array);
//--- 0이 아닌 배열 요소만 사용합니다
if(size>0)
{
out="{";
for(int i=0;i<size;i++)
{
//--- 문자열에 대한 값 수집
out+=StringFormat(" %G;",m_array[i]);
}
out+=" }";
}
//--- 결과
return(out);
}
//+------------------------------------------------------------------+
//| Class "Matrix" |
//+------------------------------------------------------------------+
class CMatrix
{
private:
CRow m_rows[];
public:
//--- 생성자 및 소멸자
CMatrix(void);
CMatrix(int rows) { ArrayResize(m_rows,rows); }
~CMatrix(void){};
//--- 행렬 크기 가져오기
int Rows() const { return(ArraySize(m_rows)); }
int Cols() const { return(Rows()>0? m_rows[0].Size():0); }
//--- 열의 값을 CRow 행 형식으로 반환합니다
CRow GetColumnAsRow(const int col_index) const;
//--- 행렬 값이 있는 문자열을 반환합니다
string String(void) const;
//--- 인덱싱 연산자가 번호별로 문자열을 반환합니다
CRow *operator[](int i) const { return(GetPointer(m_rows[i])); }
//--- 덧셈 연산자
CMatrix operator+(const CMatrix &m);
//--- 곱셈 연산자
CMatrix operator*(const CMatrix &m);
//--- 대입 연산자
CMatrix *operator=(const CMatrix &m);
};
//+------------------------------------------------------------------+
//| 기본 생성자, 크기가 0인 행 배열을 만듭니다 |
//+------------------------------------------------------------------+
CMatrix::CMatrix(void)
{
//--- 행렬의 행 수 0
ArrayResize(m_rows,0);
//---
}
//+------------------------------------------------------------------+
//| 열 값을 CRow 형식으로 반환합니다 |
//+------------------------------------------------------------------+
CRow CMatrix::GetColumnAsRow(const int col_index) const
{
//--- 열에서 값을 가져오는 변수
CRow row();
//--- 행렬의 행 수
int rows=Rows();
//--- 행 수가 0보다 크면 작업을 실행합니다
if(rows>0)
{
//--- 인덱스 col_index 가 있는 열의 값을 수신할 배열
double array[];
ArrayResize(array,rows);
//--- 배열 채우기
for(int i=0;i<rows;i++)
{
//--- i행의 열 수 확인 - 배열의 경계를 초과할 수 있습니다
if(col_index>=this[i].Size())
{
Print(__FUNCSIG__,": Error! Column number ",col_index,"> row size ",i);
break; // 행이 초기화되지 않은 객체가 됩니다
}
array[i]=this[i][col_index];
}
//--- 배열 값을 기반으로 CRow 행 생성
row=array;
}
//--- 결과
return(row);
}
//+------------------------------------------------------------------+
//| 두 행렬의 합 |
//+------------------------------------------------------------------+
CMatrix CMatrix::operator+(const CMatrix &m)
{
//--- 전달된 행렬의 행 및 열 수
int cols=m.Cols();
int rows=m.Rows();
//--- 추가 결과를 수신할 행렬
CMatrix res(rows);
//--- 행렬의 크기가 일치해야 합니다
if(cols!=Cols() || rows!=Rows())
{
//--- 덧셈 불가
Print(__FUNCSIG__,": 두 행렬을 추가하지 못했습니다. 크기가 다릅니다");
return(res);
}
//--- 보조 배열
double arr[];
ArrayResize(arr,cols);
//--- 추가할 행으로 이동
for(int i=0;i<rows;i++)
{
//--- 배열에 행렬 문자열을 추가한 결과 쓰기
for(int k=0;k<cols;k++)
{
arr[k]=this[i][k]+m[i][k];
}
//--- 행렬 행에 배열 배치
res[i]=arr;
}
//--- 행렬 덧셈의 결과를 반환
return(res);
}
//+------------------------------------------------------------------+
//| 두 행렬의 곱 |
//+------------------------------------------------------------------+
CMatrix CMatrix::operator*(const CMatrix &m)
{
//--- 첫 번째 행렬의 열 수, 행렬에 전달된 행 수
int cols1=Cols();
int rows2=m.Rows();
int rows1=Rows();
int cols2=m.Cols();
//--- 추가 결과를 수신하는 매트릭스
CMatrix res(rows1);
//--- 행렬은 조직되어야 합니다
if(cols1!=rows2)
{
//--- 곱셈 불가
Print(__FUNCSIG__,": 두 행렬을 곱하지 못했습니다. 형식이 호환되지 않습니다 "
"- 첫 번째 요인의 열 수는 두 번째 요인의 행 수와 같아야 합니다");
return(res);
}
//--- 보조 배열
double arr[];
ArrayResize(arr,cols1);
//--- 곱셈 행렬의 행을 채웁니다
for(int i=0;i<rows1;i++)// 행을 통과합니다
{
//--- 수신 배열 재설정
ArrayInitialize(arr,0);
//--- 행의 요소 통과
for(int k=0;k<cols1;k++)
{
//--- CRow의 에 행렬 m의 열 k 값을 취합니다
CRow column=m.GetColumnAsRow(k);
//--- 두 행을 곱하고 i번째 요소에 벡터의 스칼라 곱하기 결과를 기록합니다
arr[k]=this[i]*column;
}
//--- 행렬의 i 행에 배열 arr[] 배치
res[i]=arr;
}
//--- 두 행렬의 곱을 반환합니다
return(res);
}
//+------------------------------------------------------------------+
//| 할당 작업 |
//+------------------------------------------------------------------+
CMatrix *CMatrix::operator=(const CMatrix &m)
{
//--- 행 수 찾기 및 설정
int rows=m.Rows();
ArrayResize(m_rows,rows);
//--- 전달된 행렬의 행 값으로 행을 채웁니다
for(int i=0;i<rows;i++) this[i]=m[i];
//---
return(GetPointer(this));
}
//+------------------------------------------------------------------+
//| 행렬의 문자열 표현 |
//+------------------------------------------------------------------+
string CMatrix::String(void) const
{
string out="";
int rows=Rows();
//--- 문자열로 형성
for(int i=0;i<rows;i++)
{
out=out+this[i].String()+"\r\n";
}
//--- 결과
return(out);
}
|