C言語関係掲示板

過去ログ

No.615.30桁の四則演算?

[戻る] [ホームページ]
No.5882

30桁の四則演算?
投稿者---翔(2003/04/21 15:48:47)


どうもこんにちは。
今、30桁の二つの数値を入力して、その和、差、積、商を
求めるプログラムというものをやっているのですが、配列を
用いて計算するというのはわかるのですが、
いざプログラムにしようとするとなかなかできずに困っています。
とりあえずこんな感じにやってみたのですが・・・。
#include <stdio.h>
main()
{
	char a[30]={'a'};
	char b[30]={'b'};
	char plus[31];
	char mainasu[30];
	char kakeru[60];
	char waru[30];

   printf( "aの値は:");
   scanf( "%s", &a);
   printf( "bの値は:");
   scanf( "%s", &b);

   printf( "%d\n", plus);
   printf( "%d\n", mainasu);
   printf( "%d\n", kakeru);
   printf( "%d\n", waru);
   return 0;
} 

どなたかご教授ください。

No.5885

Re:30桁の四則演算?
投稿者---すず(2003/04/21 18:03:01)


こんにちわ。

>今、30桁の二つの数値を入力して、その和、差、積、商を

> char a[30]={'a'};

失礼ですが、変数と配列の違いを理解されていますでしょうか?
char型の変数がとりうる値は−128〜127ですので、
翔さんのやりたいとする30桁の計算はおろか、
3桁の計算でもすぐアウトになるかと・・・。
あと、文字と文字列の違いも理解されてますでしょうか?

> printf( "%d\n", plus);

おそらく計算結果を表示するものと私は推測したのですが、
翔さんの宣言では、plusのアドレスが10進数で表示されるだけですが・・・。

わたしの誤理解でしたら申し訳ありません。
パっと見でソースを解読するとそう推測してしまいました。


No.5951

Re:30桁の四則演算?
投稿者---翔(2003/04/25 09:37:14)


どうも。返事が遅れてしまいました。
わたしの考えでは文字型で入力した数字を数値型に変換させてから
計算させるというものでしたが、それでは文字型で入力する意味が
ないので、考え方が間違っていたのだと思いました。
うーむ・・どう考えればよいのでしょうか・・。

No.5953

Re:30桁の四則演算?
投稿者---とおりすがり(2003/04/25 10:18:36)


>今、30桁の二つの数値を入力して、その和、差、積、商を

30桁というわりには

    char a[30]={'a'};
配列が30バイトしか確保されていない。

文字列を入力するなら
>   scanf( "%s", &a);
ではなく
>   scanf( "%s", a);




No.5954

Re:30桁の四則演算?
投稿者---とおりすがり(2003/04/25 10:24:46)


>   scanf( "%s", &a);
これでも入るか・・・
まぎらわしい表記だな・・・

No.5961

Re:30桁の四則演算?
投稿者---かずま(2003/04/25 11:28:29)


> 今、30桁の二つの数値を入力して、その和、差、積、商を
> 求めるプログラムというものをやっているのですが、配列を
> 用いて計算するというのはわかるのですが、
> いざプログラムにしようとするとなかなかできずに困っています。

誰かが多倍長計算の書いてあるところを紹介するだろうと思って放って
おいたのですが、とりあえず、和と積だけを適当にでっち上げました。
割り算は難しいでしょう。負の値をどう扱うかも考えてみてください。
#include <stdio.h>
#include <string.h>

void get_int(const char *msg, char *a)
{
    char buf[31];  int i;

    fputs(msg, stdout);
    scanf("%30s", buf);
    memset(a, 0, 30);
    for (i = strlen(buf); i > 0; )
        *a++ = buf[--i] - '0';
}

void put_int(const char *msg, const char *a)
{
    int i = 30;

    fputs(msg, stdout);
    while (--i > 0 && a[i] == 0)
        ;
    do putchar(a[i] + '0'); while (i--);
    putchar('\n');
}

void add(char *c, const char *a, const char *b)
{
    int i;

    memset(c, 0, 31);
    for (i = 0; i < 30; i++) {
        c[i] += a[i] + b[i];
        if (c[i] >= 10)
            c[i+1]++,  c[i] -= 10;
    }
}

void multiply(char *c, const char *a, const char*b)
{
    int i, j;

    memset(c, 0, 60);
    for (i = 0; i < 30; i++) {
        for (j = 0; j < 30; j++)
            c[i+j] += a[i] * b[j];
        for (j = 0; j < 59; j++)
            c[j+1] += c[j]/10, c[j] %= 10;
    }
}

int main(void)
{
    char a[30], b[30], wa[31], seki[60];

    get_int("a = ", a);
    get_int("b = ", b);
    add(wa, a, b);
    multiply(seki, a, b);
    put_int("wa = ", wa);
    put_int("seki = ", seki);
    return 0;
}


No.5963

Re:30桁の四則演算?
投稿者---とおりすがり(2003/04/25 11:42:56)


>誰かが多倍長計算の書いてあるところを紹介するだろうと思って放って

じゃぁ
http://www.google.com/search?num=50&lr=lang_ja&q=%E5%A4%9A%E5%80%8D%E9%95%B7%E8%A8%88%E7%AE%97

No.5964

Re:30桁の四則演算?
投稿者---とおりすがり(2003/04/25 11:50:57)


こっちのほうがいいか?
http://www.google.com/search?num=50&lr=lang_ja&q=%E5%A4%9A%E5%80%8D%E9%95%B7

No.6073

Re:30桁の四則演算?
投稿者---翔(2003/04/30 17:10:54)


どうも〜。かずまさん、ありがとうございます。
一応ここまでやってみましたが、引き算でマイナスをつける処理と、
割り算の処理がわかりませんでした。
よいアドバイスがありましたらお願いします。
#include <stdio.h>
#include <string.h>
#include "shisoku.h"

int main(void)
{
    char a[31];
    char b[31];
    char addition[31];                                    /* 足し算 */
    char subtraction[31];                                /* 引き算 */
    char multiplication[70];                            /* 掛け算 */
//    char division[30];                                    /* 割り算 */

    get_int_a(a);
    get_int_b(b);
    add(addition, a, b);                                /* 足し算の計算処理 */
    sub(subtraction, a, b);                                /* 引き算の計算処理 */
    multiply(multiplication, a, b);                        /* 掛け算の計算処理 */
//    div(division, a, b);                                /* 割り算の計算処理 */
    put_int_add("addition = ", addition);                /* 足し算の結果表示 */
    put_int_sub("subtraction = ", subtraction);            /* 引き算の結果表示 */
    put_int_multi("multiplication = ", multiplication);    /* 掛け算の結果表示 */
//    put_int_div("division = ", division);

    return 0;
}

void get_int_a(char *a)
{
    char buf[31];
    int i;

    printf("aの値は?>");
    scanf("%30s", buf);
    memset(a, 0, 30);
    for (i = strlen(buf); i > 0; ) {
        *a++ = buf[--i] - '0';
    }
}

void get_int_b(char *b)
{
    char buf[31];
    int i;

    printf("bの値は?>");
    scanf("%30s", buf);
    memset(b, 0, 30);
    for (i = strlen(buf); i > 0; ) {
        *b++ = buf[--i] - '0';
    }
}

/*******************************************/
/*
                足し算の計算処理
*/
/*******************************************/
void add(char *c, const char *a, const char *b)
{
    int i;

    memset(c, 0, 31);
    for (i = 0; i < 30; i++) {
        c[i] += a[i] + b[i];
        if (c[i] >= 10) {
            c[i+1]++;  
            c[i] -= 10;
        }
    }
}

/*******************************************/
/*
                引き算の計算処理
*/
/*******************************************/
void sub(char *c, const char *a, const char *b)
{
    int i;

    memset(c, 0, 31);
    for (i = 0; i < 30; i++) {
        c[i] += a[i] - b[i];
        if (c[i] < 0) {
            c[i+1]--; 
            c[i] += 10;
        }
        if (c[29] == 9) {
            for (i = 0; i < 30; i++) {
                c[i] = b[i] - a[i];
                if (c[i] < 0) {
                    c[i+1]--; 
                    c[i] += 10;
                }
            }
        }
    }
}

/*******************************************/
/*
                掛け算の計算処理
*/
/*******************************************/
void multiply(char *c, const char *a, const char *b)
{
    int i, j;

    memset(c, 0, 65);
    for (i = 0; i < 30; i++) {
        for (j = 0; j < 30; j++) 
            c[i+j] += a[j] * b[i];

        for (j = 0; j < 59; j++) {
            c[j+1] += c[j] / 10;
            c[j] %= 10;
        }
    }
}

/*******************************************/
/*
                割り算の計算処理
*/
/*******************************************/
void div(char *c, const char *a, const char *b)
{
    int i, j;

    memset(c, 0, 31);
    for (i = 0; i < 30; i++) {
        for (j = 0; j < 30; j++) 
            c[i-j] += a[j] / b[i];

        for (j = 0; j < 59; j++) {
            c[j+1] += c[j] / 10;
            c[j] %= 10;
        }
    }
}

/*******************************************/
/*
        足し算の計算結果の出力表示処理
*/
/*******************************************/
void put_int_add(const char *msg, const char *a)
{
    int i = 31;

    fputs(msg, stdout);
    
    while (i-- > 1 && a[i] == 0)
            ;

    do {
        putchar(a[i] + '0'); 
    } while (i--);
    putchar('\n');
}

/*******************************************/
/*
        引き算の計算結果の出力表示処理
*/
/*******************************************/
void put_int_sub(const char *msg, const char *a)
{
    int i = 31;

    fputs(msg, stdout);
    
    while (i-- > 1 && a[i] == 0)
            ;

    do {
        putchar(a[i] + '0'); 
    } while (i--);
    putchar('\n');
}

/*******************************************/
/*
        掛け算の計算結果の出力表示処理
*/
/*******************************************/
void put_int_multi(const char *msg, const char *a)
{
    int i = 64;

    fputs(msg, stdout);
    
    while (i-- > 1 && a[i] == 0)
            ;

    do {
        putchar(a[i] + '0'); 
    } while (i--);
    putchar('\n');
}

/*******************************************/
/*
        割り算の計算結果の出力表示処理
*/
/*******************************************/
void put_int_div(const char *msg, const char *a)
{
    int i = 30;

    fputs(msg, stdout);
    
    while (i-- > 1 && a[i] == 0)
            ;

    do {
        putchar(a[i] + '0'); 
    } while (i--);
    putchar('\n');
}


No.6074

Re:30桁の四則演算?
投稿者---翔(2003/04/30 17:12:45)


上のプログラムに使われているヘッダファイルです。
shisoku.h
#if !defined ___SHISOKU_H
    #define ___SHISOKU_H    

    void get_int_a(char *a);
    void get_int_b(char *b);
    void add(char *c, const char *a, const char *b);
    void sub(char *c, const char *a, const char *b);
    void multiply(char *c, const char *a, const char *b);
//    void div(char *c, const char *a, const char *b);
    void put_int_add(const char *msg, const char *a);
    void put_int_sub(const char *msg, const char *a);
    void put_int_multi(const char *msg, const char *a);
//    void put_int_div(const char *msg, const char *a);

#endif


No.6146

Re:30桁の四則演算?
投稿者---翔(2003/05/08 15:29:26)


引き算まではできたのですが、割り算が全然わかりません。
この1週間ずっと考えてるのですが、全くだめです。。
どうにかお助けください。

No.6147

Re:30桁の四則演算?
投稿者---とおりすがり(2003/05/08 15:47:57)


>引き算まではできたのですが、割り算が全然わかりません。

ふと思ったのだが

割り算とは引き算の繰り返しのような・・・
かけ算とは足し算の繰り返しのような・・・

No.6148

Re:30桁の四則演算?
投稿者---翔(2003/05/08 16:54:21)


>割り算とは引き算の繰り返しのような・・・
>かけ算とは足し算の繰り返しのような・・・

それはわかってますが、あらゆる方法を試してもうまくいきませんでした。
ですから参考として手本を見せていただきたいのです。

No.6150

Re:30桁の四則演算?
投稿者---かずま(2003/05/08 19:10:31)


> 引き算まではできたのですが、割り算が全然わかりません。

引き算ができたのなら、それを見せてください。
負の数をどう表現しましたか。

正の数の割り算なら簡単です。
#include <stdio.h>
#include <string.h>

#define N  30

int get_int(const char *msg, char *a)
{
    char buf[N+1];  int i;

    fputs(msg, stdout);
    scanf("%s", buf);
    memset(a, 0, N);
    for (i = strlen(buf); i > 0; )
        *a++ = buf[--i] - '0';
    return 0;
}

void put_int(const char *msg, const char *a)
{
    int i = N;

    fputs(msg, stdout);
    while (--i > 0 && a[i] == 0)
        ;
    do putchar(a[i] + '0'); while (i--);
    putchar('\n');
}

int add(char *c, const char *a, const char *b)
{
    int i, carry = 0;

    for (i = 0; i < N; i++) {
        c[i] = a[i] + b[i] + carry;
        carry = (c[i] > 9);
        if (carry) c[i] -= 10;
    }
    return carry;
}

int subtract(char *c, const char *a, const char *b)
{
    int i, borrow = 0;

    for (i = 0; i < N; i++) {
        c[i] = a[i] - b[i] - borrow;
        borrow = (c[i] < 0);
        if (borrow) c[i] += 10;
    }
    return borrow;
}

int divide(char *q, char *r, const char *a, const char *b)
{
    int i;  char x[2*N];  static char zero[N];

    if (memcmp(b, zero, N) == 0) return 1;
    memcpy(x, a, N);  memset(x + N, 0, N);
    for (i = N-1; i >= 0; i--) {
        for (q[i] = 0; q[i] < 10; q[i]++)
            if (subtract(x + i, x + i, b)) break;
        add(x + i, x + i, b);
    }
    memcpy(r, x, N);
    return 0;
}

int main(void)
{
    char a[N], b[N], q[N], r[N];

    get_int("a: ", a);
    get_int("b: ", b);
    if (divide(q, r, a, b)) return puts("zero divide"), 1;
    put_int("a / b = ", q);
    put_int("a % b = ", r);
    return 0;
}


No.6152

Re:30桁の四則演算?
投稿者---かずま(2003/05/08 19:34:40)


> 引き算ができたのなら、それを見せてください。

失礼しました。
No.6073 に引き算のプログラムがあったんですね。
でも、負の数は扱えない。

No.6178

Re:30桁の四則演算?
投稿者---翔(2003/05/09 09:25:23)


おはようございます。
かずまさんどうもありがとうございます。
とりあえず現在のソースを貼ります。

#include <stdio.h>
#include <string.h>
#include "shisoku.h"

int main(void)
{
	char a[31];
	char b[31];
	char b1[31];
	char addition[31];									/* 足し算 */
	char subtraction[31];								/* 引き算 */
	char multiplication[70];							/* 掛け算 */
	int d=0;
	int f=0;
//	char division[30];									/* 割り算 */
	char e[256];

	get_int_a(a, &d);
	get_int_b(b, &f);
	add(addition, a, b);								/* 足し算の計算処理 */
	sub(subtraction, a, b, d, f);						/* 引き算の計算処理 */
	strcpy(e,subtraction);
	multiply(multiplication, a, b);						/* 掛け算の計算処理 */
//	div(b1, division, a, b, d, f);						/* 割り算の計算処理 */
	put_int_add("addition = ", addition);				/* 足し算の結果表示 */
	put_int_sub("subtraction = ", subtraction);			/* 引き算の結果表示 */
	put_int_multi("multiplication = ", multiplication);	/* 掛け算の結果表示 */
	put_int_div("division = ", division);				/* 割り算の結果表示 */

	return 0;
}

void get_int_a(char *a, int *d)
{
    char buf[31];
	int i;

    printf("aの値は?>");
    scanf("%30s", buf);
    memset(a, 0, 30);

	/* 桁数を取得 */
	*d = strlen(buf);

	for (i = strlen(buf); i > 0; ) {
		*a++ = buf[--i] - '0';	
	}

}

void get_int_b(char *b, int *f)
{
    char buf[31];
	int i;

    printf("bの値は?>");
    scanf("%30s", buf);
    memset(b, 0, 30);
	*f = strlen(buf);
    for (i = strlen(buf); i > 0; ) {
        *b++ = buf[--i] - '0';
	}
}

/*******************************************/
/*
				足し算の計算処理
*/
/*******************************************/
void add(char *c, const char *a, const char *b)
{
    int i;

    memset(c, 0, 31);
    for (i = 0; i < 30; i++) {
        c[i] += a[i] + b[i];
        if (c[i] >= 10) {
            c[i+1]++;  
			c[i] -= 10;
		}
    }
}

/*******************************************/
/*
				引き算の計算処理
*/
/*******************************************/
void sub(char *c, const char *a, const char *b, int d, int f)
{
	int i;
	int j=0;
	
	memset(c, 0, 31);
	/* aとbの桁数が同じで末の桁が同じ数字の時 */
	if (d == f && a[d-1] == b[f-1]) {
		for (i = 0; i < d; i++) {
			c[i] += a[i] - b[i];		
			if (c[i] < 0) {			
				c[i+1]--; 
				c[i] += 10;
			}
		}
		if (c[d-1] == 9) {
			for (i = f; i >= 0; i--) {
				c[i] = b[i] - a[i];		
				if (c[i] < 0) {			
					c[i+1]--; 
					c[i] += 10;
				}
			}
			/* cの桁数を取得 */
			j = strlen(c);
			/* 桁の末尾にマイナスをつける */
			c[j] = '-' - '0';
		}
	}
	/* aとbの桁数が同じでaよりもbのほうが大きい時 */
	if (d == f && a[d-1] < b [f-1]) {
		for (i = 0; i < d; i++) {
			c[i] += b[i] - a[i];
			if (c[i] < 0) {
				c[i+1]--;
				c[i] += 10;
			}
		}
		j = strlen(c);
		c[j] = '-' - '0';
	}
	/* aよりもbの桁数が大きい時 */
	if (d < f) {
		for (i = 0; i < f; i++) {
			c[i] += b[i] - a[i];
			if (c[i] < 0) {
				c[i+1]--; 
				c[i] += 10;
			}
		}
		j = strlen(c);
		c[j] = '-' - '0';
	}
	/* aの桁数がbよりも大きい時 */
	if (d > f) {
		for (i = d; i >= 0; i--) {
			c[i] += a[i] - b[i];		
			if (c[i] < 0) {			
				c[i+1]--; 
				c[i] += 10;
			}
		}
	}
	/* aとbの桁数が同じでaのほうがbよりも大きい時 */
	if (d == f && a[d-1] > b[f-1]) {
		for (i = d; i >= 0; i--) {
			c[i] += a[i] - b[i];		
			if (c[i] < 0) {			
				c[i+1]--; 
				c[i] += 10;
			}
		}
	}
}

/*******************************************/
/*
				掛け算の計算処理
*/
/*******************************************/
void multiply(char *c, const char *a, const char *b)
{
    int i, j;

    memset(c, 0, 65);
    for (i = 0; i < 30; i++) {
        for (j = 0; j < 30; j++) {
            c[i+j] += a[j] * b[i];
		}

		for (j = 0; j < 59; j++) {
            c[j+1] += c[j] / 10;
			c[j] %= 10;
		}
    }
}

/*******************************************/
/*
		足し算の計算結果の出力表示処理
*/
/*******************************************/
void put_int_add(const char *msg, const char *a)
{
    int i = 31;

    fputs(msg, stdout);
    
	while (i-- > 1 && a[i] == 0)
			;

    do {
		putchar(a[i] + '0'); 
	} while (i--);
    putchar('\n');
}

/*******************************************/
/*
		引き算の計算結果の出力表示処理
*/
/*******************************************/
void put_int_sub(const char *msg, const char *a)
{
    int i = 31;

    fputs(msg, stdout);
    
	while (i-- > 1 && a[i] == 0)
			;

    do {
		putchar(a[i] + '0'); 
	} while (i--);
    putchar('\n');
}

/*******************************************/
/*
		掛け算の計算結果の出力表示処理
*/
/*******************************************/
void put_int_multi(const char *msg, const char *a)
{
    int i = 64;

    fputs(msg, stdout);
    
	while (i-- > 1 && a[i] == 0)
			;

    do {
		putchar(a[i] + '0'); 
	} while (i--);
    putchar('\n');
}


No.6196

Re:30桁の四則演算?
投稿者---かずま(2003/05/10 01:22:14)


> とりあえず現在のソースを貼ります。

なぜ、get_int_a と get_int_b など、同じ事をする関数が
2つ以上あるんでしょうか。

符号をつけてみました。
#include <stdio.h>
#include <ctype.h>
#include <string.h>

#define N   31

static char zero[N];

static int add0(char *c, const char *a, const char *b)
{
    int i, carry = 0;

    for (i = 0; i < N-1; i++) {
        c[i] = a[i] + b[i] + carry;
        carry = (c[i] > 9);
        if (carry) c[i] -= 10;
    }
    return carry;
}

static int sub0(char *c, const char *a, const char *b)
{
    int i, borrow = 0;

    for (i = 0; i < N-1; i++) {
        c[i] = a[i] - b[i] - borrow;
        borrow = ((unsigned)c[i] > 9);
        if (borrow) c[i] += 10;
    }
    return borrow;
}

static int mul0(char *c, const char *a, const char *b)
{
    int i, j;  char x[2*(N-1)] = { 0 };

    for (i = 0; i < N-1; i++) {
        for (j = 0; j < N-1; j++)
            x[i+j] += a[i] * b[j];
        for (j = 0; j < N-1; j++)
            if (x[j]) x[j+1] += x[j] / 10, x[j] %= 10;
    }
    memcpy(c, x, N-1);
    return memcmp(x + N - 1, zero, N-1) != 0;
}

static int div0(char *q, char *r, const char *a, const char *b)
{
    int i;  char x[2*(N-1)];

    if (memcmp(b, zero, N-1) == 0) return 1;
    memcpy(x, a, N-1);  memset(x + N - 1, 0, N-1);
    for (i = N-2; i >= 0; i--) {
        for (q[i] = 0; q[i] < 10; q[i]++)
            if (sub0(x + i, x + i, b)) break;
        add0(x + i, x + i, b);
    }
    memcpy(r, x, N-1);
    return 0;
}

int add(char *c, const char *a, const char *b)
{
    if (a[N-1] == b[N-1]) {
        c[N-1] = a[N-1];
        return add0(c, a, b);
    }
    c[N-1] = a[N-1] ? sub0(c, b, a) : sub0(c, a, b);
    if (c[N-1]) sub0(c, zero, c);
    return 0;
}

int subtract(char *c, const char*a, const char *b)
{
    char x[N];

    x[N-1] = 1 - b[N-1];
    memcpy(x, b, N-1);
    return add(c, a, x);
}

int multiply(char *c, const char *a, const char *b)
{
    c[N-1] = a[N-1] ^ b[N-1];
    return mul0(c, a, b);
}

int divide(char *c, const char *a, const char *b)
{
    char x[N-1];

    c[N-1] = a[N-1] ^ b[N-1];
    return div0(c, x, a, b);
}

int get_int(const char *msg, char *a)
{
    int i, c;

    if (msg) fputs(msg, stdout);
    while ((c = getchar()) == ' ' || c == '\t' || c == '\n')
        ;
    a[N-1] = 0;
    switch (c) {
    case '-': a[N-1] = 1;
    case '+': c = getchar();
    }
    if (!isdigit(c)) { ungetc(c, stdin); return 1; }
    for (i = 0; i < N-1; i++) {
        if (!isdigit(c)) { ungetc(c, stdin); break; }
        a[N-1 - 1 - i] = c - '0';
        c = getchar();
    }
    if (i != N-1) {
        memcpy(a, a + N - 1 - i, i);
        memset(a + i, 0, N - 1 - i);
    }
    return 0;
}

void put_int(const char *msg, const char *a, const char *msg2)
{
    int i = N-1;

    if (msg) fputs(msg, stdout);
    if (a[N-1]) putchar('-');
    while (--i > 0 && a[i] == 0)
        ;
    do putchar(a[i] + '0'); while (i--);
    if (msg2) fputs(msg2, stdout);
}

int main(void)
{
    char a[N], b[N], c[N];

    while (!get_int("a: ", a) && !get_int("b: ", b)) {
        if (add(c, a, b)) puts("[+] overflow");
        else put_int("  a + b = ", c, "\n");

        if (subtract(c, a, b)) puts("[-] overflow");
        else put_int("  a - b = ", c, "\n");

        if (multiply(c, a, b)) puts("[*] overflow");
        else put_int("  a * b = ", c, "\n");

        if (divide(c, a, b)) puts("zero divide");
        else put_int("  a / b = ", c, "\n");
    }
    return 0;
}