• ベストアンサー

多項式のユークリッドの互除法を解くプログラミング

二つの多項式(AとB)を割り算し、出た余り(C)を割る数、割る数(B)を割られる数にし、余りが0になるまで割り算を行うプログラムをC言語で作っています。 例 A÷B=商・・・余りC B÷C=商・・・余りD Y÷Z=商・・・余り0 以下失敗したプログラム #include <stdio.h> int main(void) { int m,m2,i,j,k; int a[1000],b[1000],c[1000],d[1000],e[1000]; puts("何次の多項式ですか?"); printf("1つめ:"); scanf("%d",&m); printf("2つめ:"); scanf("%d",&m2); puts("1つめの多項式の係数を入力してください。"); for(i=m;i>=0;i--){ scanf("%d",&a[i]); } puts("2つめの多項式の係数を入力してください。"); for(i=m2;i>=0;i--){ scanf("%d",&b[i]); } printf("一回目の商は\n"); for(l = 1 ;l>=0;l--){ for(k=m-m2;k>=0;k--){ c[k]=a[m - (m - m2 - k)]/b[m2]; printf("%d ",c[k]);//商の表示 j = m2; for(i = m - (m - m2 - k);i>= m - (m - m2 - k) - m2 ;i--){ d[i]=a[i]-c[k]*b[j]; a[i]=d[i]; j=j-1; } } m=m2; m2=m2-1; a[l]=b[l]; b[l]=d[l]; } printf("\n"); for(i = m - (m - m2 - k);i>= m - (m - m2 - k) - m2+1 ;i--){ d[i]=a[i]-c[0]*b[j]; a[i]=d[i]; j=j-1; printf("%d ",d[i]); } return(0); } 間違いがわかる人は教えてください、お願いします

質問者が選んだベストアンサー

  • ベストアンサー
回答No.3

#include <stdio.h> #include <math.h> /* 質問文から続けて書いたら思ったより嵌った 変数名を整理したりすればもっときれいになるはずだし, Oh-Orangeさんのように構造体なりを使えばこんなに苦労はしないと思う。 */ int main(void) { int m,m2,i,j,k,l,n,p,q; double a[1000],b[1000],c[1000],d[1000],e[1000]; puts("何次の多項式ですか?"); printf("1つめ:"); scanf("%d",&m); printf("2つめ:"); scanf("%d",&m2); puts("1つめの多項式の係数を入力してください。"); for(i=m;i>=0;i--){ scanf("%lf",&a[i]); } puts("2つめの多項式の係数を入力してください。"); for(i=m2;i>=0;i--){ scanf("%lf",&b[i]); } q = 1; l = 0; while(q == 1){ q = 0; printf("--\n"); printf("%d回目の商は",l+1); for(k=m-m2;k>=0;k--){ c[k] = a[m - (m - m2 - k)] / b[m2]; printf("%lfx^%d + ",c[k],k);//商の表示 j = m2; for(i = m - (m - m2 - k);i>= m - (m - m2 - k) - m2 ;i--){ d[i]=a[i]-c[k]*b[j]; a[i] = d[i]; j = j - 1; } } printf("\n"); for (k = m2;k >=0 ;k--){ a[k] = b[k]; } for (k = m-m2;k >=0 ;k--){ b[k] = d[k]; if (d[k] != 0){ q = 1; } } for (k = 0;k <= 1000;k++){ d[k] = 0; } while(b[m2] == 0){ m2 = m2 - 1; } if (m2 <= 0){ break; } printf("q:%d\n",q); p = m2 - 1; m = m2; m2 = p; l = l + 1; printf("\n"); } if (q == 0){ printf("割り切れた"); }else{ printf("割り切れなかった"); } return(0); }

その他の回答 (3)

回答No.4

多分順番間違えている printf("q:%d\n",q); p = m2 - 1; m = m2; m2 = p; l = l + 1; printf("\n"); while(b[m2] == 0){ m2 = m2 - 1; } if (m2 <= 0){ break; }

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.2

★最初に >多項式のユークリッドの互除法を解くプログラミング…  ↑  この多項式とは配列を用いて桁数の大きい数を表現して計算させるものでしょうか?  俗に『多倍長演算』という事ですか? ・もしもそのような演算でユークリッドの互除法を行うならば、まず割り算(あまり)を  正確に計算できるルーチンを作ります。  割り算のアルゴリズムをきちんと整理しないと何時まで経っても完成しませんので  小学生で習った『筆算』の方法を参考に実装します。 ・考え方は次の通り。  (1)『被除数の桁数』を『除数の桁数』に合わせて切り出す。→これが最終的な『あまり』の数。  (2)『被除数』÷『除数』を行う。→ここがポイント  (3)『被除数』-『中間の商』×『除数』=『中間のあまり』  (4)『被除数』を1要素分だけ左方向にずらして1要素分の『被除数』を補う。  (5)(1)へ戻り繰り返し計算。  (6)『被除数』の一の位までを繰り返したら除算ループを終了  このアルゴリズムで除算を行うと同時にあまりも計算されます。 ・質問にあるソースをざっと見た限りでは『除算』そのものが多項式に対応していないような気がします。  多項式÷配列の1つ=1回目という考えて行っているのでしょうかね。ソースは?  この方法だと収束するまでに時間が掛かりすぎますし、あまりお勧めではありません。  まずは1つの数の『多項式』を分かりやすい構造体を使って表現して減算、除算、除算(剰余)の  それぞれの処理を関数で分けたほうが良いですよ。見やすいしね。→main一本(1つの関数)では  処理が長くなりすぎますので分けましょう。 サンプル: // 構造体の一例 struct bignum_t {  int len;  int num[ 1000 ]; } stBIGNUM, *lpBIGNUM; // プロトタイプ宣言の一例 int cmp( lpBIGNUM a, lpBIGNUM b ); // 比較 void sub( lpBIGNUM ans, lpBIGNUM a, lpBIGNUM b ); // 減算 void mul( lpBIGNUM ans, lpBIGNUM a, lpBIGNUM b ); // 乗算 void div( lpBIGNUM ans, lpBIGNUM a, lpBIGNUM b, lpBIGNUM r ); // 除算&剰余(あまり) // 肝心の除算(サブ関数を4つに分ければ分かりやすい) void div( lpBIGNUM ans, lpBIGNUM a, lpBIGNUM b, lpBIGNUM r ) {  int bottom = (a->len - b->len);    if ( a->len == 0 ){   return; // aがゼロの処理  }  if ( b->len == 0 ){   return; // bがゼロの処理(ゼロ除算エラーなど)  }  // ans構造体の初期化(ゼロで埋める)  memset( ans, 0, sizeof(stBIGNUM) );  // 筆算方式の除算  for ( divStart(r,a,bottom) ; ; divShift(r,a->num[bottom]) ){   ans->num[ bottom ] = divValue( r, b );      if ( --bottom < 0 ){    lenAdjust( ans ); // lenメンバの補正    return;   }  } } // サブ関数のプロトタイプ宣言 void lenAdjust( lpBIGNUM ans ); void divStart( lpBIGNUM r, lpBIGNUM a, int bottom ); void divShift( lpBIGNUM r, int value ); int divValue( lpBIGNUM r, lpBIGNUM b ); 以上。参考に。

opossamu
質問者

お礼

わざわざわかりやすくサンプルまでありがとうございますm(_ _)m C言語始めたばかりで構造体や関数もよくわからないので勉強してみます^^;

回答No.1

ちょっと待ってね。まだ考えてなくて少ししたら考えてみるつもり。 当時ソース張ったけど, あれ,整形し忘れて「あちゃー」っと回答してから思い(汗) そのまま締め切られた記憶が蘇ってきて 懐かしかったから (↓当時の) http://aol.okwave.jp/qa3514558.html

opossamu
質問者

お礼

あの時はありがとうございましたm(_ _)m 本当に助かりました! 最終的に多項式の因数分解のプログラムを作らなきゃいけないんですが正直実力以上のことをやらされてるものでかなり欝です・・・

関連するQ&A

  • C言語で多項式の割り算のプログラム

    C言語で多項式の割り算のプログラムを作っているんですができません 以下プログラム #include <stdio.h> int main(void) { int m,m2,i,i2,j,k; int a[1000],b[1000],c[1000],d[1000]; puts("何次の多項式ですか?"); printf("1つめ:"); scanf("%d",&m); printf("2つめ:"); scanf("%d",&m2); puts("1つめの多項式の係数を入力してください。"); for(i=m;i>=0;i--){ scanf("%d",&a[i]); } puts("2つめの多項式の係数を入力してください。"); for(i=m2;i>=0;i--){ scanf("%d",&b[i]); } k=m-m2; c[k]=a[m]/b[m2]; printf("商の次数は%dです。\n",k); j=m2-1; for(k=m-m2;k>=0;k--){ for(i=m-1;i>=0;i--){ d[i]=a[i]-c[k]*b[j]; a[i]=d[i]; c[k-1]=a[i]/b[m2]; j=j-1; } printf("%d ",c[k]); } return(0); } 原因は  for(k=m-m2;k>=0;k--){ for(i=m-1;i>=0;i--){ d[i]=a[i]-c[k]*b[j]; a[i]=d[i]; c[k-1]=a[i]/b[m2]; j=j-1; } printf("%d ",c[k]); } で、iのfor文が終わった後kのfor文が更新され、またiのfor文が始まったときにa[i]が最初に入力された値に変わってしまうからだと思うんですが直せません 誰か教えてくださいm(_ _)m

  • 関数化について

    何度も質問しているんですがまた行き詰ってしまいました 以前解答をいただき自分なりに進めていき以下のことができるようになりました 1、多項式の係数を入力し、多項式(A)をつくる。 2、それを微分したもの(A’)で割る。→A÷A’=商・・・余りB 3、出てきた余り(B)を割る数、ひとつ前の作業で割る数だったもの(A’)を割られる数にする。 4、割る数(B)の最高次の係数の2乗をしたもの(a^2)を割られる数(A’)にかける。(擬除法) 5、割り算を行う。→(a^2)×A’÷B 6、余りが0になるまで3~5を繰り返す。(0にならなければ終わり) 7、割り切れたときの割る数がAとA’の最大公約数Dとなる(正確には最大公因数?) とここまでできるようになりました。 で、次にさらにまた 8、A÷D=E 9、DとEでユークリッドの互除法により最大公約数Gを求める 10、E÷G=P→PがAのi次の平方因子 11DをAとしDが無平方になるまで1~10を繰り返す。 といったことをやらなければいけないんですが、 いい加減関数を使わないと長すぎるので同じ作業を簡略化するため関数化することにしました。 で、微分のプログラムは関数化できたんですが、ユークリッドの互除法のプログラムが難しくて関数化できません。 わかる方お願いしますm(_ _)m 以下プログラム #include <stdio.h> #include <math.h> int main(void){ int m,m2,i,j,k,l,n,p,q; int a[1000],b[1000],c[1000],d[1000],e[1000]; puts("何次の多項式ですか?"); printf("何次:"); scanf("%d",&m); puts("多項式の係数を入力してください。"); for(i=m;i>=0;i--){ scanf("%d",&a[i]); //e[i]=a[i]; //printf("e[i]=%d\n",e[i]); } derivative(&m,a,&m2,b); printf("微分された多項式は:"); for(i=m2;i>=0;i--){ printf("%dx^%d+ ",b[i],i); } printf("\n\n"); q = 1; l = 0; while(q == 1){ printf("割られる数は:"); for(i=m;i>=0;i--){ a[i]=a[i]*(b[m2]*b[m2]); printf("%dx^%d + ",a[i],i); } q = 0; printf("\n上のは割る数の最高の次数の係数の2乗をかけたもの:b[m2]=%d\n",b[m2]); printf("--\n"); printf("%d回目の商は\n",l+1); for(k=m-m2;k>=0;k--){ c[k] = a[m - (m - m2 - k)] / b[m2]; printf("%dx^%d + ",c[k],k);//商の表示 j = m2; for(i = m - (m - m2 - k);i>= m - (m - m2 - k) - m2 ;i--){ d[i]=a[i]-c[k]*b[j]; a[i] = d[i]; j = j - 1; } } printf("\n"); for (k = m2;k >=0 ;k--){ a[k] = b[k]; } printf("余り:"); for (k = m2-(m-m2);k >=0 ;k--){ b[k] = d[k]; printf("%dx^%d + ",b[k],k); if (d[k] != 0){ q = 1; } } for (k = 0;k <= 1000;k++){ d[k] = 0; } printf("q:%d\n",q); p = m2 - 1; m = m2; m2 = p; l = l + 1; printf("\n"); while(b[m2] == 0){ m2 = m2 - 1; } if (m2 <= 0){ break; } } if (q == 0){ printf("割り切れた"); }else{ printf("割り切れなかった"); } return(0); } int derivative(int *m, int a[],int *m2, int b[]) { int i; for(i=*m;i>0;i--){ b[i-1]=i*a[i]; } *m2=*m-1; return(0); }

  • C言語 プログラミング 行列演算

    下記のプログラムのおかしい点と解決法を教えてください。 コンパイルは通りますがうまく動きません。。 #include<stdio.h> #define MAX 500 int main(void){ int matrA[MAX][MAX],matrB[MAX][MAX],matrC[MAX][MAX],l,m,n,i,j,k; printf("lとmを入力してください:"); scanf("%d",&l); scanf("%d",&m); printf("行列Aを入力してください"); for(i=0;i<l;i++){ printf(">"); for(j=0;l<m;j++){ scanf("%d",&matrA[i][j]); } printf("\n"); } printf("nを入力してください(m = %d):",m); scanf("%d",&n); printf("行列Bを入力してください"); for(i=0;i<m;i++){ printf(">"); for(j=0;j<n;j++){ scanf("%d",&matrB[i][j]); } printf("\n"); } printf("C=\n"); for(i=0;i<l;i++){ for(j=0;j<n;j++){ for(k=0;k<m;k++){ matrC[i][j]+=matrA[i][k]*matrB[k][j]; } printf("%d",matrC[i][j]); } printf("\n"); } }

  • C言語 プログラミングで行詰まりました…

    標準入力(キーボード)からi,jk,nの値を入力し、次の漸化式を計算し、X_0からX_nまで求めるプログラムを作成したいのですが、うまく表示されません。どかがおかしいのかご指摘お願いします。 <漸化式> X_n=(a+b)/X_(n-1) , X_0=c(n=0) ================================================================== #include<stdio.h> float f_X(int a,int b,float c) { float y; y=(a+b)/c; return y; } int main (void) { int number,i,j; float k,l,n,X; printf("i:"); scanf("%d", &i); printf("j:"); scanf("%d", &j); printf("k:"); scanf("%f", &k); printf("n:"); scanf("%f", &n); X=k; printf("X_0= %.6f\n",X); for(number=1;number<=n;number++) { l=f_X(i,j,X); printf("X_%d= %.6f \n",number,l); X=l; } return 0; } ===================================================================

  • 5×5行列、固有値、固有ベクトル

    5つの値を入力し、それぞれの相対比を求めて行列にして、固有値と固有ベクトルを求めたいのですが、分からないので教えて下さい。下のプログラムは固有値を求めるものです。これは過去の質問にあったプログラムを少し変えてみたのですが、値が出てこないのでどうすればうまく出てくるのか教えて下さい。それと、固有ベクトルを求めるプログラムも教えて下さい。宜しくお願いします。 #include <math.h> #include <stdlib.h> #include <stdio.h> int main(void) { int i, j, k, l; double max,theta,x,y,a[5][5],b[5]; printf("値1: "); scanf("%d",&b[0]); printf("値2: "); scanf("%d",&b[1]); printf("値3: "); scanf("%d",&b[2]); printf("値4: "); scanf("%d",&b[3]); printf("値5: "); scanf("%d",&b[4]); printf("行列\n"); for(j=0;j<5;j++){ for(k=0;k<5;k++){ a[j][k]=b[k]/b[j]; printf("%1.3f ",a[j][k]); } printf("\n"); } while(1){ max=0; for(i=0;i<5;i++){ for(j=0;j<5;j++){ if (i!=j && max<fabs(a[i][j])){ max=fabs(a[i][j]); k=i; l=j; } } } if (max<1.0e-6) break; theta=(a[k][k]!=a[l][l])? atan2(-2*a[k][l],a[k][k]-a[l][l])/2:M_PI/4; for(i=0;i<5;i++){ x=a[i][k]; y = a[i][l]; a[i][k] = cos(theta) * x - sin(theta)*y; a[i][l] = sin(theta) * x + cos(theta)*y; } for (j=0;j<5;j++){ x=a[k][j]; y=a[l][j]; a[k][j]=cos(theta)*x-sin(theta)*y; a[l][j]=sin(theta)*x+cos(theta)*y; } } printf("固有値\n"); for (i=0;i<5;i++){ printf("%1.3f\n",a[i][i]); } return 0; }

  • ユークリッド互除法

    ユークリッド互除法を使用して最大公約数を求めるプログラムを、C言語で書いてみました。 #include <stdio.h> main() { int a, b, t; scanf("%d %d", &a, &b); if(a<b){ t=a; a=b; b=t; } while(b != 0){ t = a % b; a = b; b = t; } printf("GCD = %d\n", a); return 0; } これを、もっと簡略化できるらしいのですが、これ以上できることはありますか? どう考えてもわかりません

  • C言語プログラミングの問題がわかりません・・・。

    ただいまC言語を勉強している者です。 【入力するデータ数と各データ(整数)を入力していき,0 以下の整数の数,正の整数の数,0 以下の整数の合計,正の整数の合計を求めるプログラムを作成せよ。】 という問題があり、とりあえず #include "stdio.h" void main() { int i,j,k,l=0,m=0,goukeisei=0,goukeifu=0; printf("入力するデータ数:"); scanf("%d",&i); for(j=1;j<=i;j++); { printf("データを入力してください(整数):"); scanf("%d",&k); if(k>0){ l++; goukeisei+=k; }else{ m++; goukeifu+=k; } } printf("正の整数の数%d\n",l); printf("0以下の整数の数%d\n",m); printf("正の整数の合計%d\n",goukeisei); printf("0以下の整数の合計%d\n",goukeifu); } と作ってみたのですが、入力するデータ数の繰り返しがされません(1回入力して終わりになってしまいます);; for文の使い方が間違っているのでしょうか・・・ 詳しい方教えてくださいm( _ _ )m 尚環境はXPでVC++2008を使っています。よろしくお願いします。

  • C言語の配列の使い方について質問です。

    以下のプログラムを配列を使って見やすくしたいのですが、どのように作ったら良いでしょうか? 宜しくお願いします。 #include<stdio.h> int main(void) { int a, b, c, d, e, f, g, h, i, j, k, l, m ,n, o; /*5段目の処理*/ for(a = 1; a <= 15; a++) { for(b = 1; b <= 15; b++) { if(a == b) continue; for(c = 1; c <= 15; c++) { if(a == c || b == c) continue; for(d = 1; d <= 15; d++) { if(a == d || b == d || c == d) continue; for(e = 1; e <= 15; e++) { if(a == e || b == e || c == e || d == e) continue; // printf("%d %d %d %d %d\n", a, b, c, d, e); ////4段目//// if(a>b){ f=a-b; } else if(a<b){ f=b-a; } if(b>c){ g=b-c; } else if(b<c){ g=c-b; } if(c>d){ h=c-d; } else if(c<d){ h=d-c; } if(d>e){ i=d-e; } else if(e<d){ i=e-d; } // printf(" %d %d %d %d \n", f, g, h, i); /////3段目//// if(f>g){ j=f-g; } else if(f<g){ j=g-f; } if(g>h){ k=g-h; } else if(g<h){ k=h-g; } if(h>i){ l=h-i; } else if(h<i){ l=i-h; } // printf(" %d %d %d \n", j, k, l); /////2段目//// if(j>k){ m=j-k; } else if(j<k){ m=k-j; } if(k>l){ n=k-l; } else if(k<l){ n=l-k; } // printf(" %d %d \n", m, n); /////三段目///// if(m>n){ o=m-n; } else if(m<n){ o=n-m; } // printf(" %d \n", o); if(a != b != c != d != e != f != g != h != i != j != k != l != m != n != o){ printf("%d %d %d %d %d\n", a, b, c, d, e); printf(" %d %d %d %d \n", f, g, h, i); printf(" %d %d %d \n", j, k, l); printf(" %d %d \n", m, n); printf(" %d \n", o); } } } } } } }

  • 下記プログラミングについて

    下のプログラミングの解説ができる方がいましたら教えてください! どう頑張っても理解できなくて困っています;; もしかしたら間違っているところがあるかもしれませんが、よろしくお願いします。 ---------------------------------------------------------------- #include<stdio.h> #include<math.h> main() { int A,B,C,t,h,i,j,k; int sum_column,sum_row,diagonal1,diagonal2; int conf,diag,seed,max; int U[101][101],V[101][101]; int rand(); A=1,B=1,C=1; printf("Please define the pueen problem size(5-100).\n"); scanf("%d", &max); printf("Please input a seed(0-999).\n"); scanf("%d", &seed); for(i=1; i<=seed; i++){ U[1][1]=rand(); }; for(i=1; i<=max; i++){ for(j=1; j<=max; j++){ U[i][j] = -(abs(rand() % 8)); V[i][j]=0; }; };   /* Main program */ t=0; diag=1; while((diag>0)&&(t<500)){ diag=0; for(i=1; i<=max; i++){ for(j=1; j<=max; j++){ sum_column=0; sum_row=0; for(k=1; k<=max; k++){ sum_row=sum_row+V[i][k]; sum_column=sum_column+V[k][j]; } diagonal1=0; k=1; while(((j+k)<=max)&&((i-k)>=1)){ diagonal1=diagonal1+V[i-k][j+k]; k++; } k=1; while(((j-k)>=1)&&((i+k)<=max)){ diagonal1=diagonal1+V[i+k][j-k]; k++; } k=1; while(((j+k)<=max)&&((i+k)<=max)){ diagonal2=diagonal2+V[i+k][j+k]; k++; } k=1; while(((j-k)>=1)&&((i-k)>=1)){ diagonal2=diagonal2+V[i-k][j-k]; k++; } k=1; h=0; conf=1; if(sum_column == 0) h=1; if(sum_row == 0) h++; if((sum_column+sum_row==2) && (diagonal1<2) && (diagonal2<2)) conf=0; U[i][j]=U[i][j]-A*(sum_row+sum_column-2)-B*(diagonal1+diagonal2)+C*h; if(U[i][j]>8) U[i][j]=8; if(U[i][j]<-8) U[i][j]=-8; if(U[i][j]>0) V[i][j]=1; else V[i][j]=0; diag=diag+conf; }; }; t++; printf("t=%d\n", t); if((t % 15) < 5) C=4; else C=1; }; printf("the number of iteretion steps=%d\n", t); printf("\n"); for(i=1; i<=max; i++){ for(j=1; j<=max; j++){ if(j==max){ if(V[i][j]==1) printf("*\n"); else printf("-\n"); } else{ if(V[i][j]==1) printf("* "); else printf("- "); } } } }

  • c言語で行列の積の値を求める

    行列の成分を入力した後に、 入力された行列は X = 1 2 3 4 5 6 7 8 9 10 11 12 Y = 1 5 2 6 3 7 4 8 のように表示して、(上の数字は適当です。) 行列 X と行列 Y の積を求めて結果を表示するプログラムが作りたいのですが、上手く表示できなくて困っています。 #include <stdio.h> int main(void) { double A[10][10]; double B[10][10]; double C[10][10]; int i,j,m,n,p,k; printf("行列xの行数は?:"); scanf("%d",&m); printf("行列xの列数(行列yの行数)は?:"); scanf("%d",&n); printf("行列yの列数は?:"); scanf("%d",&p); printf("行列xを入力してください。\n"); for (i = 0; i < m; i++) { for (j = 0; j < n; j++) { scanf("%d", &A[i][j]); } } printf("行列yを入力してください。\n"); for (i = 0; i < n; i++) { for (j = 0; j < p; j++) { scanf("%d", &B[i][j]); } } この後にどうすればいいのか教えてください。 よろしくお願いします。

専門家に質問してみよう