・三次・四次方程式の解は、定式化されている。その解の計算を STL を利用し、行う。
三次方程式の、実数係数、複素数係数の二つ計算を示す。
四次方程式の、実数係数、複素数係数の二つの計算を示す。
・多次元の方程式の根を、Newton-Raphson法を用いて、求める。
・常微分方程式を Rungekutta で算出する。
・最小二乗法で、データを近似する。
・通常の関数(数値群)をフーリエ変換する。(FFTやDFTではない)
1、概要
三次方程式の解の式は、既にあり、カルダーノの公式と呼ばれる。
複素数解を含んだ式に判別式Dを用いず、カルダーノ法により 9 ケースの数値を算出した。このように判別
式を使用しない場合、 9 ケースが生じる。しかし、ケース低減を目論んだ一般に取られる一実根がある事を
前提にした算出法でも、5ケースについて計算しなければならない。この 9 ケースは、許容されるのではな
いだろうか。
2、三次方程式(コード1)
コードについて
・三次方程式の解には、a1/3 (a;数)がある。この時に、複素数になる可能性があるので、
その複素数から実数項や虚数項を取り出すために、real_unit(1.0,0.0)、imag_unit(0.0,1.0) を設けた。
・知られているように、解は、位相が 120° 異なった成分で構成されているので、
絶対値が同じで、位相だけを 120° 変える位相転換用複素数
complex<double> shift(-1.0/2.0,sqrt(3.0)/2.0);
を設け、計算を行った。これをコードから抜き出した個所を下記にしめす。
y[0]= 1.0*pow(y1,1/3.0) +1.0*pow(y2,1/3.0);
y[1]= 1.0*pow(y1,1/3.0) +shift*pow(y2,1/3.0);
y[2]= 1.0*pow(y1,1/3.0)+shift*shift*pow(y2,1/3.0);
y[3]= shift*pow(y1,1/3.0) +1.0*pow(y2,1/3.0);
y[4]= shift*pow(y1,1/3.0) +shift*pow(y2,1/3.0);
y[5]= shift*pow(y1,1/3.0)+shift*shift*pow(y2,1/3.0);
y[6]=shift*shift*pow(y1,1/3.0) +1.0*pow(y2,1/3.0);
y[7]=shift*shift*pow(y1,1/3.0) +shift*pow(y2,1/3.0);
y[8]=shift*shift*pow(y1,1/3.0)+shift*shift*pow(y2,1/3.0);
・transform()の使い方として、関数オブジェクトを二通り作り、これを用いた計算を行った。
なお、STL(vectorやstring)でない通常の関数 y1,y2 を 参照(&)にして、計算を行っている。
この部分を下記にしめす。
complex<double>c0(0.0,0.0);
transform(&y1,&y1+1,&y2,&c0,csum0);//transform使用例。
complex<double>c1(0.0,0.0);
transform(&y1,&y1+1,&y2,&c1,binary_csum1());//transform使用例。
transform()に対しては、この方法は、好ましくないやり方で、warning が出る。
&y1 を y1.begin()、&y1+1 を y1.end()、&y2 を y2.begin() とするのが正しいのだが、y1
や y2 が
vector でないので、正しいやり方は適用できない。しかし、transform() を使い、計算させたい時がある
ので、忘備として記載した。
なお、計算過程で生じる中間ファイルのデータ in3eq.csv を remove で削除した。
三次方程式の適用は、管内を空気が流れる時、側壁からの熱放散の微分方程式の特性根算出に例がある。
また、ガロワは、120° 位相を変えていくと、元に戻るという事から、循環の考えを考えたと聞く。
3、使用したSTLと関数
xxx.is_open、xxx.eof()、strtod()、xxx.c_str()、vector、vector<complex<double>>、v1.push_back()、
v1.resize(v1.size())、pow(complex,1.0/3.0)、abs()、
120度の位相角のシフトに 0.5+i・sqrt(3)/2.0 の使用、transform()の使用
1、概要
実数係数の三次方程式の解を求める数値計算は、上記 1、三次方程式(実数係数)に示した通りである。
複素数係数の三次方程式の場合は、上記 コード1 を部分的に変更する事で、算出できる。
計算の考え方は、実数係数の場合と同じく判別式を使用しない方法で、9 ケースの場合で算出した。
複素係数の三次方程式では、データの読み込みを本ホームページ c++ STL 適用例の 9 に示した事があ
るので、この変換を用いないで、入力の読み込みを行った。単純にした。
2、三次方程式 複素数係数(コード1-1)
コードについて
・コードの計算は、殆ど、実数係数の場合と同じである。
なお、計算過程で生じる中間ファイルのデータ in3eq.csv を remove で削除した。
1、常微分方程式 Runge-Kutta法(コード5)
関数オブジェクトであるclass文、typedef文をfunction文として使用した例を示した。
2、コードの説明
Runge-Kuttal法は、k1の初期値を決め、その初期値によりk2の初期値を求め、更にk3の初期値を順次求める方
法である。初期値をx0,y0 とすると、下記のように解を得ていく方法である。
x1=x0+h;
と x1 を決めた時、
k1=h*f(x0,y0);k2=h*f(x0+h/2,yo+k1/2);k3=h*f(x0+h/2,y0+k2/2);k4=h*f(x0+h,y0+k3);
として、
k=(k1+k2+k3+k4)/6;y=y+k;x=x+h
を求める。
関数オブジェクト binary_function を文字数が多いので、binary_f と短くするとCompilerから拒否される。
また、class文のfunction文的使用は常に動作するが、typedef文は時折動作しない場合がある。
class文、typedef文であれ、同じ常微分方程式であれば、同じ結果を得る。
class文、typedef文の中に、微分方程式を記述する方法で計算を行ったが、 微分方程式の式を外部から読込む
手法があれば、便利である。VSの方式しかないのだろうか。
3、使用したSTLと関数
operator()、binary_function
参考図書;C言語と数値計算法
1、概要
1)最小二乗 直線近似(コード6)
・STL/algorithmを使用し、直線近似を記述した。直線近似の傾きと切片を 6行で求めた。
相関係数を2通り(残差、偏差)の方法で、求めた。残差は、2種のSTLで、偏差は、rsqc_pmccと表示した。
・コードの説明
コードで注目すべき点は、直線近似の y=a・x+b の係数 a,b を STL のみで、算出している点である。
直線近似をSTLのみの表現で示した個所を下記に抜書きする。
下記で x は、 x 軸の値を示し、y は x に対応した y 軸の値しめす。
xの平均値を求める
double average_x=accumulate(u.begin(),u.begin()+u.size()/2,0.0)/(u.size()/2);
yの平均
double average_y=accumulate(u.begin()+u.size()/2,u.end(),0.0)/(u.size()/2);
xとyの積の平均 (この xと y の積をとる理由は、多くの本に記載してあるので参照方)
double average_xy=inner_product(u.begin(),u.begin()+u.size()/2,u.begin()+u.size()/2,0.0)/(u.size()/2)
x の二乗の平均
double average_xx=inner_product(u.begin(),u.begin()+u.size()/2,u.begin(),0.0)/(u.size()/2);
直線近似の y=a・x+b の a の値
double a=(average_xy-average_x*average_y)/(average_xx-average_x*average_x);
直線近似の y=a・x+b の b の値
double b=(average_y*average_xx-average_x*average_xy)/(average_xx-average_x*average_x);
上記のように、直線近似の係数を accmulate と inner_product で求めた。
コードの説明
最小二乗法を適用する xi と yi=f(xi) の値を同じ vector u に入れて計算している。
vector()で u.begen() と u[0] の関係
u.begin()は、u[0]の前にある。そこからu[0]を含んだ以降を示す。u.begin()は u[0] からは始まらない。
u.begin()+u.size()/2 は、その後ろにあるものの前までである。
2)最小二乗 多項式近似 データ列数1列(コード7)
STLの数値algorithmを使用し、多項式近似計算を記述した。残余値により、相関係数の算出を行った。
csv形式で、x,yのデータ読込み法は、string形で読み、strtodで変換した。これは、第0章のcsvデータ読込み
に、記載しているので、参照方。
また、多項式近似における連立一次方程式の解法は、第4章の連立一次方程式のGauss-Jordan法(vector適用)
に記載しているので、ご参照方。
transformに2項関数オブジェクトを適用し、xのn乗を算出した。
最大値がある要素位置を知る方法として、*max_element() は、要素の最大値を示すので、これを利用して、
以下の手法で、
double dfabsmax=*max_element(ddd.begin(),ddd.end());
int inum;
for(i=0;i<(int)ddd.size();i++) if(ddd[i]-dfabsmax ==0.00) inum=i;
とし、最大値を示す要素の位置を inum から得る事ができる。
更に容易な方法は、 max_element (ポインターが無い)はアドレスを示すので、ddd.begin()と組合わせると
、ddd.begin()からの位置として最大値の要素位置を得る事ができる。これを以下に示す。
int inum=max_element(ddd.begin(),ddd.end())-ddd.begin();
3)最小二乗 多項式近似 データ列自由(コード8)
上記に加えて、csv形式で、xとy1,y2,y3…yn のデータ読み、多項式近似計算が出来るようにした。
相関係数の算出を行った。
データの列および行数に制限のないコードである。
4)最小二乗 1/xの-n乗 多項式近似(コード9)
xの増加に対して、yが低減する現象がある。xのプラスn乗の多項式で近似できないケースである。
このために作成した。考えを変え、本文のみで近似式算出を行った。
上記(コード8)の2項関数nthmultiplies内のxの積個所と本文の検証計算のpow個所のxを1/xに変更するとxの
マイナスn乗の多項式近似を求める事が出来る。
なお、混合形態は今は断念。
2、使用したSTLと関数
u.assign()、accumulate()、inner_product()、v.resize(v.size())、u[i+u.size()]、u.begin()、u.end()、
v.push_back()、transform()、setw()、setprecision()、s.clear()
3、参考図書
STLによるC++プログラミング、C言語と数値計算法
1、概要
FFT、DFTではデータ個数に指定があるが、これは、1周期の入力データ数を限定しない一般の方法である。
Fourier級数の係数算出はcos,sinの級数で行った。 得た係数から、sin、cosの関数による再構成を行った。
2、フーリエ級数展開(コード10)
周期を [0,2d] として、計算した。
3、使用したSTLと関数
xxx.is_open、xxx.eof()、strtod()、xxx.c_str()、vector、v1.push_back()、v1.resize(v1.size())、
accumulate()、abs()、atan()、break、(int)v1.size()。
4、その他
vector<complex<double>>の使用で少ない行数で、fourier級数算出が可能になったが、その算出の次数と再
構成で釈然としない箇所があり、cos、sinで計算した。