No.18266![]() |
もんきっきのプログラムソース1 投稿者---もんきっき(2004/11/20 00:50:07) |
||
返信遅くなりましたm(__)m2つに分けて 貼りますので一つのプログラムとして 見てください。f(^^; #include<stdio.h> #include<string.h> int change_int(char A) { switch(A){ case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; } return 0; } int addition(int a[],int b[]) { int i,j=0,c=0,add[41]; for(i=0;i<=40;i++) add[i]=0; for(i=40;i>=0;i--){ add[i] = a[i] + b[i] + c; if(add[i]>=10){ c = add[i]/10; add[i] = add[i] % 10; } else c = 0; } for(i=0;i<=40;i++){ if(add[i]==0) j++; else break; } printf("x+y="); for(i=j;i<=40;i++) printf("%d",add[i]); printf("\n"); return j+40; } int subtraction(int a[],int b[]) { int i,j,c=0,d=0,e=0,p,sub[41]; for(i=0;i<=40;i++) sub[i]=0; for(i=0;i<=40;i++){ if(a[i]==0) c++; else break; } for(i=0;i<=40;i++){ if(b[i]==0) d++; else break; } if(c>d) p=0; else if(c==d){ for(i=0;i<=40;i++){ if(a[i]==b[i]){ e++; continue; } else{ if(a[i]<b[i]) p=0; else p=1; } break; } } else p=1; if(p==0){ for(i=40;i>=0;i--){ if(b[i]<a[i]){ sub[i] = b[i] + 10 - a[i]; b[i-1] = b[i-1] - 1; } else sub[i] = b[i] - a[i]; } } else{ for(i=40;i>=0;i--){ if(a[i]<b[i]){ sub[i] = a[i] + 10 - b[i]; a[i-1] = a[i-1] - 1; } else sub[i] = a[i] - b[i]; } } j = 0; for(i=0;i<=40;i++){ if(sub[i]==0) j++; else break; } if(e==41) printf("x-y=0"); else if(p==0){ printf("x-y=-"); for(i=j;i<=40;i++) printf("%d",sub[i]); } else{ printf("x-y="); for(i=j;i<=40;i++) printf("%d",sub[i]); } printf("\n"); if(e==41) return 80; else return j+40; } |
No.18267![]() |
Re:もんきっきのプログラムソース2 投稿者---もんきっき(2004/11/20 00:51:05) |
||
int multiplication(int a[],int b[]) { int i,j,k,m,n,c,d,mul[82]; for(i=0;i<=81;i++) mul[i]=0; k=0; for(i=40;i>=0;i--){ c=0; for(j=40;j>=0;j--){ mul[j+41-k]=a[j]*b[i]+mul[j+41-k]+c; if(mul[j+41-k]>=10){ c=mul[j+41-k]/10; mul[j+41-k]=mul[j+41-k]%10; } else c=0; } k++; } j=0; for(i=0;i<=81;i++){ if(mul[i]==0) j++; else break; } printf("x*y="); for(i=j;i<=81;i++) printf("%d",mul[i]); printf("\n"); return j-1; } int keta(int a) { return 81-a; } void main() { char x[41], y[41]; int a[41], b[41]; int i, m, n ,c,d,e; for(i=0;i<=40;i++){ a[i]=0; b[i]=0; } printf("x="); scanf("%s", &x); printf("y="); scanf("%s", &y); m = strlen(x); for(i=0;i<m;i++) a[i] = change_int(x[i]); for(i=m-1;i>=0;i--) a[41-m+i] = a[i]; for(i=0;i<=40-m;i++) a[i]=0; n = strlen(y); for(i=0;i<n;i++) b[i] = change_int(y[i]); for(i=n-1;i>=0;i--) b[41-n+i] = b[i]; for(i=0;i<=40-n;i++) b[i]=0; c = addition(a,b); printf("桁数…%d桁\n",keta(c)); d = subtraction(a,b); printf("桁数…%d桁\n",keta(d)); e = multiplication(a,b); printf("桁数…%d桁\n",keta(e)); } |
No.18269![]() |
Re:もんきっきのプログラムソース1 投稿者---ぽこ(2004/11/20 01:45:30) |
||
取り合えず、change_int()から。 '0'が入力されたとき、0が返って来ますが、正常の値かエラー値か判断できません。 エラーの時、-1を返すようにしたのが以下の例です。 int change_int(char c) { return isdigit(c) ? c - '0': -1; } |
No.18270![]() |
Re:もんきっきのプログラムソース1 投稿者---もんきっき(2004/11/20 02:06:54) |
||
>ぽこさんへ 先ほどのアドバイスを 実行しても変わりませんでした。(泣) 例えばx=22,y=5を入力してもらって実行 してもらうと本当は110なのですが60と 出力されます。またx=1000,y=99と入力 すると-9-18-90などと出力されてしまい ます。 |
No.18271![]() |
Re:もんきっきのプログラムソース1 投稿者---ぽこ(2004/11/20 02:13:15) |
||
>>ぽこさんへ >先ほどのアドバイスを >実行しても変わりませんでした。(泣) それはそうかと。 関数が長かったので、短くしただけです^^; |
No.18272![]() |
Re:もんきっきのプログラムソース1 投稿者---ぽこ(2004/11/20 02:36:09) |
||
>例えばx=22,y=5を入力してもらって実行 >してもらうと本当は110なのですが60と >出力されます。またx=1000,y=99と入力 >すると-9-18-90などと出力されてしまい >ます。 subtraction()がおかしいですね。 繰り下がりの引き算を行ったときに、 a[i]=a[i]-1(b[i]=b[i]-1)とやってますね。 これのおかげで、次の掛け算の際にx[]とy[]の値が変わっています。 なぜ変わるかというのは、以下のURLを参考にしてください。 http://www9.plala.or.jp/sgwr-t/c/sec11-2.html (2)アドレス渡しの※の部分をよく読んで下さい。 |
No.18273![]() |
Re:もんきっきのプログラムソース1 投稿者---もんきっき(2004/11/20 03:27:54) |
||
>ぽこさんへ おお〜!!直りました! a[i]=a[i]-1(b[i]=b[i]-1)をやると 元のmain内の値が変わってしまうって ことですよね?まだアドレス渡しを習って ないので自分で先ほどのURLを見てそのように 解釈しましたが、あってるんでしょうか?f(^^; 今回のおれが作ったようなプログラムの場合は subtraction関数内で元の配列の値を引いている ので、その次に実行されるmultiplication関数では 元の値が入っていないってことですよね!? |
No.18274![]() |
Re:もんきっきのプログラムソース1 投稿者---ぽこ(2004/11/20 03:30:45) |
||
>解釈しましたが、あってるんでしょうか?f(^^; >今回のおれが作ったようなプログラムの場合は >subtraction関数内で元の配列の値を引いている >ので、その次に実行されるmultiplication関数では >元の値が入っていないってことですよね!? ということです。 |
No.18275![]() |
Re:もんきっきのプログラムソース1 投稿者---もんきっき(2004/11/20 03:40:31) |
||
ぽこさん本当にありがとうございました!! とても感謝しています!返信してくださった 方々、これからもよろしくお願いします。 |
No.18276![]() |
Re:もんきっきのプログラムソース1 投稿者---かずま(2004/11/20 13:31:30) |
||
演算と入出力は別関数にしたほうがよいのではないでしょうか。そんな プログラムを書いてみました。オーバーフローのチェックはやっていません。 #include <stdio.h> #include <string.h> #include <ctype.h> #define N 40 int add(const char *a, const char *b, char *c) { int i, x, y = 0; for (i = 0; i < N; i++) x = a[i] + b[i] + y, c[i] = (y = x >= 10) ? x - 10 : x; return y; } int sub(const char *a, const char *b, char *c) { int i, x, y = 0; for (i = 0; i < N; i++) x = a[i] - b[i] - y, c[i] = (y = x < 0) ? x + 10 : x; return y; } int mul(const char *a, const char *b, char *c) { int i, j; char x[N+1] = { 0 }; for (i = 0; i < N; i++) for (j = 0; i+j < N; j++) x[i+j] += a[i] * b[j], x[i+j+1] += x[i+j] / 10, x[i+j] %= 10; memcpy(c, x, N); return x[N]; } int input(const char *msg, char *x) { int n, i, c, minus = 0; char y[N] = { 0 }, c10[N] = { 0, 1 }; memset(x, 0, N); fputs(msg, stdout); do c = getchar(); while (isspace(c)); if (c == EOF) return EOF; if (c == '-') minus = 1, c = getchar(); else if (c == '+') c = getchar(); if (!isdigit(c)) { ungetc(c, stdin); return EOF; } do { mul(x, c10, x), y[0] = c - '0', add(x, y, x); c = getchar(); } while (isdigit(c)); ungetc(c, stdin); if (minus) y[0] = 0, sub(y, x, x); return 0; } void print(const char *pre, const char *x, const char *post) { int i; char y[N]; fputs(pre, stdout); if (x[N-1] < 5) memcpy(y, x, N); else memset(y, 0, N), sub(y, x, y), putchar('-'); for (i = N; --i > 0 && y[i] == 0; ) ; for (; i >= 0; i--) putchar(y[i] + '0'); fputs(post, stdout); } int main(void) { char x[N], y[N], z[N]; while (input("x = ", x) != EOF && input("y = ", y) != EOF) { add(x, y, z); print(" x + y = ", z, "\n"); sub(x, y, z); print(" x - y = ", z, "\n"); mul(x, y, z); print(" x * y = ", z, "\n"); } return 0; } |
No.18277![]() |
Re:もんきっきのプログラムソース1 投稿者---かずま(2004/11/20 13:58:16) |
||
input() に無駄な処理が多すぎるので訂正。 int input(const char *msg, char *x) { int n, i, c, minus = 0; static char zero[N] = { 0 }; fputs(msg, stdout); do c = getchar(); while (isspace(c)); if (c == EOF) return EOF; if (c == '-') minus = 1, c = getchar(); else if (c == '+') c = getchar(); if (!isdigit(c)) { ungetc(c, stdin); return EOF; } for (i = N; i > 0 && isdigit(c); ) x[--i] = c - '0', c = getchar(); memmove(x, x+i, N-i), memset(x+(N-i), 0, i); if (minus) sub(zero, x, x); return 0; } |
No.18285![]() |
またまた質問です。 投稿者---もんきっき(2004/11/21 00:12:54) |
||
今までの多倍長演算に割り算を加えたいと思い 作成したのですが、結果が出力されずにおわりません。 どこがおかしいでしょうか?(また長くてすいません) #include<stdio.h> #include<string.h> int change_int(char c) { switch(c){ case '0': return 0; case '1': return 1; case '2': return 2; case '3': return 3; case '4': return 4; case '5': return 5; case '6': return 6; case '7': return 7; case '8': return 8; case '9': return 9; } return 0; } int division(int a[],int b[]) { int i,c=0,d=0,f,j,n,g,h,r,t,s,u,z,v,k,tmp[82],div[41]; for(i=0;i<=40;i++) div[i]=0; for(i=0;i<=40;i++){ if(a[i]==0) c++; else break; } for(i=0;i<=40;i++){ if(b[i]==0) d++; else break; } if(c<=d){ for(i=40-(d-c);i<=40;i++){ for(n=9;n>=0;n--){ div[i]=n; k=0; for(j=0;j<=40;j++) tmp[j]=0; for(g=40;g>=0;g--){ f=0; for(h=40;h>=i;j--){ tmp[h+41-k]=div[h]*b[g]+tmp[h+41-k]+f; if(tmp[h+41-k]>=10){ f=tmp[j+41-k]/10; tmp[h+41-k]=tmp[h+41-k]%10; } else f=0; } k++; } j=0; for(r=0;r<=40;r++){ if(tmp[r+41]==0) j++; else break; } g=0; for(g=0;g<=40;g++){ if(a[g]==0) g++; else break; } if(g>j) break; else{ t=0; for(s=0;s<=40;s++){ if(a[s]==tmp[s+41]) t++; else break; } } if(a[t]>tmp[t+41]) break; } for(u=40;u>=0;i--){ if(a[u]<tmp[u+41]){ a[u] = a[u] + 10 - tmp[u+41]; a[u-1] = a[u-1] - 1; } else a[u] = a[u] - tmp[u+41]; } z=0; for(v=0;v<=40;v++){ if(a[v]==b[v]) z++; else break; } if(a[z]>b[z]) break; } } j=0; for(i=0;i<=40;i++){ if(div[i]==0) j++; else break; } if(c>d) printf("x/y=0\n"); else{ printf("x/y="); for(i=j;i<=40;i++) printf("%d",div[i]); printf("\n"); } if(c>d) return 80; else return j+40; } int keta(int a) { return 81-a; } void main() { char x[41], y[41]; int a[41], b[41],f; int i,m,n; printf("x="); scanf("%s", &x); printf("y="); scanf("%s", &y); for(i=0;i<=40;i++){ a[i]=0; b[i]=0; } m = strlen(x); for(i=0;i<m;i++) a[i]=change_int(x[i]); for(i=m-1;i>=0;i--) a[41-m+i]=a[i]; for(i=0;i<=40-m;i++) a[i]=0; n=strlen(y); for(i=0;i<n;i++) b[i]=change_int(y[i]); for(i=n-1;i>=0;i--) b[41-n+i]=b[i]; for(i=0;i<=40-n;i++) b[i]=0; f=division(a,b); printf("桁数…%d\n",keta(f)); } |
No.18286![]() |
Re:またまた質問です。 投稿者---かずま(2004/11/21 00:46:12) |
||
> for(h=40;h>=i;j--){ > for(u=40;u>=0;i--){ この 2行を修正すると、無限ループはなくなりますが、結果が正しく ならないようですね。ちょっとコードを追い切れません。 私のプログラムにも割り算をつけてみました。 #include <stdio.h> #include <string.h> #include <ctype.h> #define N 40 int add(const char *a, const char *b, char *c) { int i, x, y = 0; for (i = 0; i < N; i++) x = a[i] + b[i] + y, c[i] = (y = x >= 10) ? x - 10 : x; return y; } int sub(const char *a, const char *b, char *c) { int i, x, y = 0; for (i = 0; i < N; i++) x = a[i] - b[i] - y, c[i] = (y = x < 0) ? x + 10 : x; return y; } int mul(const char *a, const char *b, char *c) { int i, j; char x[N+1] = { 0 }; for (i = 0; i < N; i++) for (j = 0; i+j < N; j++) x[i+j] += a[i]*b[j], x[i+j+1] += x[i+j]/10, x[i+j] %= 10; memcpy(c, x, N); return x[N]; } static char zero[N] = { 0 }; static void udiv(const char *a, const char *b, char *c, int rem) { int i, j; char x[2*N] = { 0 }; memcpy(x, a, N); for (i = N; --i >= 0; ) { for (j = 0; sub(x+i, b, x+i) == 0; j++) ; add(x+i, b, x+i), c[i] = j; } if (rem) memcpy(c, x, N); } void dvd(const char *a, const char *b, char *c) { int neg = 0; char x[N], y[N]; udiv((a[N-1] < 5) ? a : (sub(zero, a, x), neg = 1, x), (b[N-1] < 5) ? b : (sub(zero, b, y), neg ^= 1, y), c, 0); if (neg) sub(zero, c, c); } void rem(const char *a, const char *b, char *c) { int neg = 0; char x[N], y[N]; udiv((a[N-1] < 5) ? a : (sub(zero, a, x), neg = 1, x), (b[N-1] < 5) ? b : (sub(zero, b, y), y), c, 1); if (neg) sub(zero, c, c); } int input(const char *msg, char *x) { int i, c, minus = 0; fputs(msg, stdout); do c = getchar(); while (isspace(c)); if (c == '-') minus = 1, c = getchar(); else if (c == '+') c = getchar(); if (!isdigit(c)) { ungetc(c, stdin); return EOF; } for (i = N; i > 0 && isdigit(c); c = getchar()) x[--i] = c - '0'; memmove(x, x+i, N-i), memset(x+(N-i), 0, i); if (minus) sub(zero, x, x); return 0; } void print(const char *pre, const char *x, const char *post) { int i; char y[N]; const char *p; fputs(pre, stdout); p = (x[N-1] < 5) ? x : (sub(zero, x, y), putchar('-'), y); for (i = N; --i > 0 && p[i] == 0; ) ; for (; i >= 0; i--) putchar(p[i] + '0'); fputs(post, stdout); } int main(void) { char x[N], y[N], z[N]; while (input("x = ", x) != EOF && input("y = ", y) != EOF) { add(x, y, z); print(" x + y = ", z, "\n"); sub(x, y, z); print(" x - y = ", z, "\n"); mul(x, y, z); print(" x * y = ", z, "\n"); dvd(x, y, z); print(" x / y = ", z, "\n"); rem(x, y, z); print(" x % y = ", z, "\n"); } return 0; } |
No.18287![]() |
Re:またまた質問です。 投稿者---かずま(2004/11/21 00:56:48) |
||
> udiv((a[N-1] < 5) ? a : (sub(zero, a, x), neg = 1, x), dvd() の中ですが、neg = 1 を neg ^= 1 に訂正します。 |
No.18288![]() |
Re:またまた質問です。 投稿者---もんきっき(2004/11/21 01:24:07) |
||
まだ文字処理関数を習っていないので かずまさんのプログラムが少し理解で きないんですが四則全て計算してこの 短さなんですね(驚 自分のは長すぎて見にくいですね(><) |
No.18300![]() |
Re:またまた質問です。 投稿者---かずま(2004/11/22 12:57:45) |
||
> まだ文字処理関数を習っていないので memcpy(c, x, N); は、for (i = 0; i < N; i++) c[i] = x[i]; と 置き換えることができます。 memmove(x, x+i, N-i), memset(x+(N-i), 0, i); は for (c = 0; c < N-i; c++) x[c] = x[c+i]; for (; c < N; c++) x[c] = 0; と置き換えてください。 isspace(c) は (c==' ' || c=='\t' || c=='\n')、 isdigit(c) は (c >= '0' && c <= '9') と置き換えることで、 文字処理関数はなくなりますが、これで理解できますか? 40桁で表現できる数は、0〜999...999 (9が 40個) ですが、これでは 負の数が表せないので、0〜499...999 (9が 39個) はそのままとし、 500...000〜999...999 を負の数として扱っています。 -1 は 0 より 1少ないので、999...999 です。 どうしても、正の数を 40桁扱いたいというのであれば、 #define N 40 を #define N 41 に変えれば済みます。 実は、割り算にはちょっと問題があって、dvd(x, y, y) とすると、 y に正しい値が返ってきません。 |
No.18308![]() |
Re:またまた質問です。 投稿者---もんきっき(2004/11/22 22:05:00) |
||
かずまさんありがとうございます。 できる限り自分で解釈してみました。 まだ習ってないことを教わってために なりました。 |