C言語関係掲示板

過去ログ

No.482.10進数→N(2から10まで)進数の変換

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

10進数→N(2から10まで)進数の変換
投稿者---Yossy(2002/11/20 23:06:49)


はじめまして、C初学者です。
C言語で皆様に質問したくスレッドを立ち上げました。
いま、10進数→N(2から10まで)進数を変換するプログラムを作っていて
方針として
・入力した数値nをlでわり、それを代入して新しいnとする
・nをlで割ったあまりをだす。
・for文にて回数をカウント
テストとして下のプログラムをつくりました
#include <stdio.h>

int main()
{
int n,l,i;
printf("input value N");
scanf("%d",&n);

printf("input value L");
scanf("%d",&l);

for ( i=0 ; n>0 ; i++ )
{
printf("余り:%d,N:%d,ベキ乗数:%d\n",n%l,n=n/l,i);
}
}
これで各回の余り*10の回数乗を全て足せば答えが出せると思い本プログ
ラムを作ろうとしたんですがいい方法が思い付きません。Cにはpowという
のでn乗は計算できるんですが、その結果をどんどん足していくというの
がうまくいきません。
ぜひ、ご教授お願いします。
下が途中結果です。
#include <stdio.h>
#include <math.h>

int main()
{
int n,m,l,i,a;
float b,c;
printf("自然数を入力して下さい:");
scanf("%d",&m);
n=m;
printf("変換したい進数(2-10まで)を入力して下さい:");
scanf("%d",&l);

for ( i=0 ; m>0 ; i++ )
{
m=m/l;
a=m%l;
b=(a)*pow((double)(10),i);
printf("%d=%.0f(%d)であり%d桁\n",n,b,l,1+i);
}
}
現在のプログラムは和を作っていく部分がうまくいかないのでいじってません。

No.3523

Re:10進数→N(2から10まで)進数の変換
投稿者---ともじ(2002/11/21 00:46:41)


こんばんは。

>いま、10進数→N(2から10まで)進数を変換するプログラムを作っていて

>これで各回の余り*10の回数乗を全て足せば答えが出せると思い本プログ
>ラムを作ろうとしたんですがいい方法が思い付きません。

配列を使うと簡単に処理できますがいかがでしょう。
#include <stdio.h>

int main(void)
{
        int n, m, l, i, j, a[32];

        printf("自然数を入力して下さい:");
        scanf("%d", &m);
        n = m;
        printf("変換したい進数(2-10まで)を入力して下さい:");
        scanf("%d", &l);

        for (i = 0; m > 0 && i < 32; i++)       {
                a[i] = m % l;
                m = m / l;
        }
        printf("%d = ", n);
        for (j = i - 1; j >= 0; j--)
                printf("%d", a[j]);
        printf("(%d)であり%d桁\n", l, i);

        return 0;
}


No.3526

Re:10進数→N(2から10まで)進数の変換
投稿者---Yossy(2002/11/21 10:53:41)


>配列を使うと簡単に処理できますがいかがでしょう。
-------------
&#65279;レス大変ありがとうございます。初学者でまだはっきり分からない部分もある
ので質問させていただきます。考え違いもあるかもしれませんがご容赦を。
なるほど和をループで足したりせずに配列を使えばいいんですね。j=3になる
とすると最初のfor文で格納されたデータが横にa[3]a[2]a[1]a[0]とならん
でる(いい表現でなくてすみません)ということでしょうか。return 0;でnull
をおくって配列を終了させてるということでいいんでしょうか。
配列を[32]とったのは必然性があるんでしょうか、小さ過ぎなければほかの
数でも良いですよね。.....質問ばかりですみません。

また配列以外のコンセプトでやる場合どのようにしたらこのプログラムのよう
になるでしょうか、私の考えた方法では破たんを招くでしょうか。できればこ
ちらも教えていただきたいです。

#配列やポインタは独学で進めていてまだなれないので、これで理解が深まるか
もしれません。また「かつ」の論理演算子も使ったことが無いので参考になり
ました本当にありがとうございます。

No.3532

Re:10進数→N(2から10まで)進数の変換
投稿者---ともじ(2002/11/21 16:38:26)


こんにちは。

>j=3になる
>とすると最初のfor文で格納されたデータが横にa[3]a[2]a[1]a[0]とならん
>でる(いい表現でなくてすみません)ということでしょうか。

例えば10を2進数に変換する場合には、最初のループ終了時(i=4)で
 a[0]=0
 a[1]=1
 a[2]=0
 a[3]=1
と格納されています。

>return 0;でnull
>をおくって配列を終了させてるということでいいんでしょうか。

いえいえ、これは最初のループで m > 0 を満たさなくなった時点で
配列へのあまりの格納は終了します。

>配列を[32]とったのは必然性があるんでしょうか、小さ過ぎなければほかの
>数でも良いですよね。.....質問ばかりですみません。

自然数mがint型なので32ビットと考え、要素数は32にしました。
int型maxの0x7fffffffを2進数に変換すると31桁必要ですが、
仮にunsignedでも大丈夫なように32桁にしました。
unsigned intのmaxは0xffffffffで2進数では32桁必要です。

>また配列以外のコンセプトでやる場合どのようにしたらこのプログラムのよう
>になるでしょうか、私の考えた方法では破たんを招くでしょうか。できればこ
>ちらも教えていただきたいです。

Yossyさんの方法ですと、次のようになります。
#include <stdio.h>
#include <math.h>

int main(void)
{
	int n, m, l, i, a;
	float b = 0.0, c;

	printf("自然数を入力して下さい:");
	scanf("%d", &m);
	n = m;
	printf("変換したい進数(2-10まで)を入力して下さい:");
	scanf("%d", &l);

	for (i = 0; m > 0; i++)
	{
		a = m % l;
		m = m / l;
		b = b + a * pow((double)(10),i);
	}
	printf("%d=%.0f(%d)であり%d桁\n", n, b, l, i);

	return 0;
}


ループの中でpowを使いますが、関数は処理のオーバヘッドが増しますので
他に回避策がある場合には使わない方がよいのです。
それからこの計算はfloat型の有効桁数に依存しますので、
255を2進変換して11111111(2)の場合にはきちんと処理できますが、
257を2進変換するあたりから正しい答えが得られなくなります。
これは、float型の有効桁数が7桁〜8桁あたりになるからです。

有効桁数とは正確な値を表せる桁数のことで、浮動小数点数の有効桁数は
仮数部の長さで決まります。仮数部の長さは処理系依存ですが、仮数部
24ビットのfloat型では、2の24乗 = 16,777,216なので8桁が有効桁数に
なります。

仮にfloat型をdouble型にしても、やはり有効桁数は15桁〜16桁あたりで、
それ以上の計算は正しく行えなくなります。


No.3536

Re:10進数→N(2から10まで)進数の変換
投稿者---Yossy(2002/11/21 23:05:14)


2つのプログラムのどちらにしてもCの詳しい知識がいりそうですね。
配列を使うというのは参考になりました。
まだ、理解ができていない部分もありますが自分で調べて、がんばってみ
ます。
このレスに時間を割いていただいたことを感謝します。