• 締切済み

これは動いてくれますか??

最小二乗法のプログラムを作ってみたのですが、 これで動きますか?? データを読みとった後から、つまり途中からなのですが・・・ $ndata、$x,$yはデータから読み取った値でこの前で使われています。 #!/usr/bin/perl # test1.pl use strict; use warnings; my $X = $x[$ndata] my $Y = $y[$ndata] my $sg =0; my $sg1 =0; my $sg2 =0; for($i; $i < $ndata;$i++;){ $sg1 = $sg1 + ($X)**2; $sg2 = $sg2 + ($X); } $sg = $ndata * $sg1 - ($sg2)**2; my $a =0; my $a1 =0; my $a2 =0; my $a3 =0; my $a4 =0; for($i; $i < $ndata;$i++;){ $a1 = $a1 + ($X)**2; $a2 = $a2 + ($Y); $a3 = $a3 + ($X); $a4 = $a4 + ($X)*($Y); } $a = ( $a1*$a2 - $a3*$a4 ) / $sg my $b =0; my $b1 =0; my $b2 =0; my $b3 =0; my $b4 =0; for($i; $i < $ndata;$i++;){ $b1 = $b1 + ($X)*($Y); $b2 = $b2 + ($X); $b3 = $b3 + ($Y); } $b = ( $ndata*$b1 - $b2*$b3) / $sg $Y = $a + ($b * $X) my $sgy =0; my $sgy1 =0; my $sgy2 =0; for($i;$i < $ndata;$i++){ $sgy2 = $sgy2 + ($Y-$a - $b*$X)**2 } $sgy1 =$sgy2 /($ndata - 2) $sgy = sqrt( $sgy1 ); my $sga =0; my $sgb =0; $sga = $sgy * sqrt( $a1 / $sg ) $sgb = $sgy * sqrt($ndata / $sg ) print "パラメータA=$a,パラメータB=$b./n"; print "Aの誤差は$sga、Bの誤差は$sgb./n";

noname#108711
noname#108711
  • Perl
  • 回答数2
  • ありがとう数3

みんなの回答

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

え, えぇと.... Perl 以外でプログラムを作った経験はありますか? for($X; $X < $ndata;$X++;){ $sg1 = $sg1 + ($X)**2; $sg2 = $sg2 + ($X); } がどのように動くか, 理解できていますか?

noname#108711
質問者

お礼

ありません。。。 ちなみにperlも始めたばかりです。 $xが2乗されて次々に足されるのが$sg1で $Xがそのまま足されていくのが$sg2 のつもりで作っているのですが。。。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

や, いくらなんでもこれではだめ. 例えば最初の for($i; $i < $ndata;$i++;){ $sg1 = $sg1 + ($X)**2; $sg2 = $sg2 + ($X); } の部分だけでも ・$i が初期化されていない ・$X が変化していない という問題がある.

noname#108711
質問者

お礼

あっ確かに・・・ $xが変化していないというのはわかります。 $iが初期化されていないというのは my $i=0; と最初に書けばよいのでしょうか??(iを変化させたい場合) for($X; $X < $ndata;$X++;){ $sg1 = $sg1 + ($X)**2; $sg2 = $sg2 + ($X); } と直せばよいのでしょうか??

関連するQ&A

  • 至急教えてください!!

    質問したのですが、初心者すぎて何を言われているか分からないので、1部取り出しました。 和の二乗と二乗の和 この二つの和を求めたいです。 プログラム途中からで$X、$Y、$ndataは既に使われています。 my $X = $x[$ndata] my $Y = $y[$ndata] my $sg =0; my $sg1 =0; my $sg2 =0; for($x; $x < $ndata;$x++;){ $sg1 = $sg1 + ($X)**2; $sg2 = $sg2 + ($X); } $sg = $ndata * $sg1 - ($sg2)**2; これが前に質問したものです。 ​http://oshiete1.goo.ne.jp/qa5603956.html​ できれば間違っているところを直したプログラムを書いていただけると嬉しいです。それと前に質問した中で、他にも違うところがあったら直していただけると助かります。

    • ベストアンサー
    • Perl
  • 弧長パラメータとは何?

    弧長パラメータは、長さ関数の逆関数によってパラメータ変換することによって得られるそうですが、何故そうやって求められるのでしょうか?そもそも、弧長パラメータの概念が今一つ分からないです。 例えば、 x(t)=(asint,acost,bt) の曲線があるとして、 これの長さ関数は x'(t)=(acost,-bsint,0)より int(0,t)||(x'(t))||dt =int(0,t)sqrt(a^2+b^2)dt =sqrt(a^2+b^2)t より、t=x/sqrt(a^2+b^2) ですから、x(t)の弧長パラメータ表示関数は、 x(s)=(asin(a/sqrt(a^2+b^2)),acos(s/sqrt(a^2+b^2)), bs/sqrt(a^2+b^2)) となると解釈して宜しいのでしょうか? 分かる方がいましたら、回答宜しくお願いします。

  • invalid operandsb to binary/エラー

    はじめましてこんにちは。 プログラミングでC言語を使っています。 y'=x^2sqrt(y)についてオイラー法で解くプログラミングを作成しているんですが,invalid operandsb to binaryとエラーが出てなかなかできません。 そのプログラミングが下に表すものなんですが /*euler2.c*/ /* オイラー法 */ /* y'=x^2*sqrt(y) */ #include <stdio.h> #include <math.h> int main() { int i; int N=10000; /* 区間の分割数 */ double a=0.0,b=2.0; /* 区間の指定([0,2]) */ double y0=1; /* 初期値 */ double x,y,h; h=(b-a)/N; /* 刻み幅の計算 */ x=a; y=y0; /* 初期条件 */ for (i=0;i<N;i++){ ★ y=y+x^2*sqrt(y)*h+(2*x*sqrt(y)+x^4/2)/2*h^2; x=x+h; printf("%g %g\n",x,y); } return 0; } ★印のあるL21にエラーが出ます。もしどこを直せばよいかわかる方お願いします。 プログラミング初心者のため、不適切な言葉等ありましたらすいません。

  • c言語

    c言語で写真の課題を出されたのですが自分のプログラムでは上手くいきません。どこが間違っているのか教えて欲しいです。 自分のプログラム #include<stdio.h> #include<math.h> int main(){ int i,j; double c,d,x,y,z; for(i=0;i<=360;i++){ c=10*cos(i*M_PI/180); d=10*sin(i*M_PI/180); if(c>=0 && d>=0){ for(j=0;j<=1000;j++){ x=0.001*j; y =x*d/c; z=1-x*x-(sqrt(x)+y)*(sqrt(x)+y); if(z<=0.0){break;} } } if(c<=0 && d>=0){ for(j=0;j<=1000;j++){ x=-0.001*j; y=x*d/c; z=1-x*x-(sqrt(-x)+y)*(sqrt(-x)+y); if(z<=0.0){break;} } } if(c<=0 && d<=0){ for(j=0;j<=1000;j++){ x=-0.001*j; y=x*d/c; z=1-x*x-(sqrt(-x)+y)*(sqrt(-x)+y); if(z<=0.0){break;} } } if(c>=0 && d<=0){ for(j=0;j<=1000;j++){ x=0.001*j; y=x*d/c; z=1-x*x-(sqrt(x)+y)*(sqrt(x)+y); if(z<=0.0){break;} } } printf("x=%lf y=%lf z=%lf\n",x,y,z); } return(0); }

  • 二点の座標から距離や角度を求めたいのですが、Matlab

    こんにちは、Matlabの初心者ですがよろしくお願いします。 ある座標、たとえば、A(x1, y1) B(x2, y2)があったとして、 この二点間の距離は、 sqrt((x2-x1)^2 + (y2-y1)^2) だと思いますが、もっと簡潔に求めることができる関数とかが導入されていたりしないかと思いました。AやBを定義しておいて、AとBだけを使うことができないかと思いました。 また、この二点を通る直線とX軸とがなす角度は、 atan(sqrt((y2-y1)^2)/sqrt((y2-y1)^2)) で求められるかと思いますが、これも同様にもっと簡潔な方法がないかと思いました。 いかがでしょうか。よろしくお願いします。

  • 関節角度の求め方

    3点{A(x1,y1),B(x2,y2),C(x3,y3)}の角ABCを求めるには以下の方法でよいのでしょうか. AB=A長 BC=B長とします. =(A長X*B長X+A長Y*B長Y)/SQRT(A長X^2+A長Y^2)/SQRT(B長X^2+B長Y^2) =ACOS(cos)*180/PI() 数学・物理学が苦手にも関わらず早急に解決しなければなりません・・・.何か簡単な方法がありましたらよろしくお願いします. よろしくお願いします.

  • 分子構造の重ねあわせ (行列、最小二乗法など?)

    すいません、化学っぽい内容の質問なのですが、 アルゴリズムは数学になると思うのでこちらで質問させていただきます。 また、説明不足を補うために一部プログラムっぽい表記をさせていただきますのでご了承ください。 現在、分子構造を比較するためのプログラムを作成しています。 そのプログラムに構造の「重ね合わせ」機能を追加したいのですが そのアルゴリズムに最小二乗法などが必要らしく、悩んでいます。 (詳細は長くなるので下に書きます) 分かる方がいましたらご教示お願いします。 よろしくお願いします。 ■重ね合わせについて 分子構造のデータは、各原子がそれぞれX, Y, Z座標の3つの値を持っています。 例えば、200原子からなる分子のデータ構造は以下のようになります。 Atom { double x; double y; double z; } Atom atom = new Atom[200]; 重ね合わせる2つの構造は原子数は同じとします。なので、分子構造2つをa1, a2とし、 対応する点の誤差をとっていくと、誤差の平均を求める計算は以下のようになります。 Atom a1 = new Atom[200]; Atom a2 = new Atom[200]; double d = 0; for (i = 0; i < a1.length; i++) d += sqrt(pow((a1[i].x-a2[i].x),2) + pow((a1[i].y-a2[i].y),2) + pow((a1[i].z-a2[i].z),2)); d = d / a1.length; このdの値が最小値をとるようにa2の原子の座標を変更することを「重ね合わせ」と定義します。 ■重ね合わせのアルゴリズムについて 基準となる構造に対し、もう一つの構造を並進や回転によって合わせる感じになると思います。 今回質問する箇所はこのアルゴリズムになります。 この際に行列計算や最小二乗法を使うことになるかと思われます。 ■質問者の考え 途中まで、しかも間違っている可能性がありますが私の考えたアルゴリズムを追記しておきます。 (i) a1, a2の重心を求める double x1 = y1 = z1 = x2 = y2 = z2 = 0; for (i = 0; i < a1.length; i++) { x1 += a1[i].x; y1 += a1[i].y; z1 += a1[i].z; x2 += a2[i].x; y2 += a2[i].y; z2 += a2[i].z; } x1 = x1 / a1.length; y1 = y1 / a1.length; z1 = z1 / a1.length; x2 = x2 / a1.length; y2 = y2 / a1.length; z2 = z2 / a1.length; a1の重心(x1, y1, z1)とa2の重心(x2, y2, z2)が求まります。 (ii) 重心の誤差を求め、誤差をa2の各原子の座標に反映させる xd = (x2 - x1); yd = (y2 - y1); zd = (z2 - z1); for (i = 0; i < a1.length; i++) { a2[i].x -= xd; a2[i].y -= yd; a2[i].z -= zd; } この方法で誤差はかなり小さくなります。しかし、最小値にはなってないと思われます。 なので、この方法が正しいのかよく分かりません。

  • V$SGAとV$PARAMETERの確認

    Oracle9iにおけるDBにおいて、 SQLによる検索速度の向上の パフォーマンスチューニングを 行わなければならなくなりました。 まず、 テーブルV$SGAとテーブルV$PARAMETERの 値を見ろと言われましたが、 パラメータAが値Bだから値Cにしろとか パラメータDが値Eだから、メモリを積めとか 定量的な対策ができるものではないらしいです。 V$SGAとテーブルV$PARAMETERって 知ってると何か特なことあるのでしょうか? ご教授宜しくお願いします。

  • C言語でsqrt(a^2+b^2)のテーブル引き

    プログラムに悩んでいるものです. とある画像処理のプログラムを組んでいるのですが,処理が遅くテーブル引きを組んでいます. 三角関数などはすんなりできたのですが,質題にもある通りsqrt(a^2+b^2)が実現できず,この場を借りて質問させていただきました. 以下にプログラムの一部を示します. ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー void filter(unsigned char* d, short *dx, short *dy, int w, int h) { ///// テーブル生成 ///// static int c_size = 0; // static 次の呼び出しでも値保持 static double *c_sqrt = NULL; // c_size = 255;              // u,v:0~255 c_sqrt = (double *)malloc(sizeof(double)*c_size*c_size); // 領域確保 for(int i=0; i<c_size; ++i){     // 有りえるすべての値を生成 for(int j=0; j<c_size; ++i){ c_sqrt[i*j] = sqrt( (double)(i*i + j*j) ); } } ///// d = sqrt(dx^2 + dy^2) ///// for(int y = 1; y < h-1; ++y){ for(int x = 1; x < w-1; ++x){ double u = (double)dx[y*w+x]; double v = (double)dy[y*w+x]; int val = (int)c_sqrt[ (int)(u*v) ] /4; if (val>255) val=255; d[y*w+x] = val; } } } ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー 見てご察し頂ける(?)と思いますが,この関数は何回も呼び出すので,上のほうででテーブル引きしようとしてます. ただ明らかなプログラム経験不足のためかうまくいってません. 個人的にはc_sqrtを別途関数c_sqrt(u,v)にしたほうがよいのかと思ってます. どういうプログラム記述をすれば,このテーブル引きが実現できるでしょうか? ご回答,お力添え,よろしくお願い致します.

  • ガウスの消去法を用いたC言語のプログラムについて

    現在あらかじめ与えられた連立方程式をガウスの消去法を用いて、 求めるというプログラムをC言語で作っています。 しかし学校ではまだ行列のやっておらず、 ガウスの消去法についても説明があやふやでした。 一応プログラムは出来たのですが明らかに無駄が多すぎて困っています。 与えられた方程式は下記の通りです。 2x + 3y + 4z = 20 3x - 2y + 5z = 14 5x + 4y - 7z = -8 プログラムは以下の通りです。 #include <stdio.h> int main(void){ double a[3][3] = {{2, 3, 4}, //(1) {3, -2, 5}, //(2) {5, 4, -7}}; //(3) double b[3] = {20, 14, -8}; double x = 0; double y = 0; double z = 0; int i; //前進消去 //(1)÷2 ・・・(1)' for(i = 0; i < 3; i++){ a[0][i] = a[0][i] / 2; } b[0] = b[0] / 2; //(2)-(1)'×3 ・・・(2)' for(i = 0; i < 3; i++){ a[1][i] = a[1][i] - a[0][i] * 3; } b[1] = b[1] - b[0] * 3; //(3)-(1)'×5 ・・・(3)' for(i = 0; i < 3; i++){ a[2][i] = a[2][i] - a[0][i] * 5; } b[2] = b[1] - b[0] * 5; //(2)'÷6.5 ・・・(2)'' for(i = 0; i < 3; i++){ a[1][i] = a[1][i] / 6.5; } b[1] = b[1] / 6.5; //(2)''×3.5 + (3) ・・・(3)'' for(i = 0; i < 3; i++){ a[2][i] = a[2][i] + a[1][i] * 3.5; } b[2] = b[2] + b[1] * 3.5; //(3)''÷3.53846でzを求める z = b[2] / a[2][1]; //後退代入 //(2)''にzを代入してyを求める a[1][1] = a[1][1] * z; y = b[1] - a[1][1]; //(1)'にyとzを代入してxを求める a[0][1] = a[0][1] * y; a[0][2] = a[0][2] * z; x = b[0] - a[0][1] - a[0][2]; printf("\n x = %f \n y = %f \n z = %f \n", x, y, z); return 0; } 制作はvc++を用いています。 ここからどうやって短くしていけばよいかがわかりせん。 アドバイスや指摘があればお願いいたします。