3進数や5進数の文字列を10進数に変換する方法

このQ&Aのポイント
  • C言語のビットシフトを使って3進数や5進数の文字列を10進数に変換する方法についてご教授ください。
  • ビットシフトを使用した3進数や5進数の文字列を10進数に変換する方法について教えてください。
  • 3進数や5進数のような2の階乗ではない進数の文字列をビットシフトを使って10進数に変換する方法が知りたいです。
回答を見る
  • ベストアンサー

3進数を10進数に変換

3進数や5進数のように2の階乗ではない任意の進数の文字列を、C言語のビットシフトを使って10進数に変換するプログラムについて、質問させていただきます。 ビットシフトを使わないで、任意の進数の文字列を10進数に変換する方法は分かっていますが、ビットシフトを使った方が非常に計算が高速で出来るので、ビットシフトを使いたいと思っています。 下記のプログラムは4進文字列を10進整数に変換するものです。2進、8進文字列の場合は、シフトするビット数を1ビット、3ビット(つまり、ans <<= 1、ans <<= 3)にすれば計算することが可能です。しかし、3進数や5進数の場合、いろいろと考えたのですが、どのようにすれば良いのか分かりません。 下記のプログラムのようにビットシフトを使って3進数や5進数の文字列を10進数に変換するには、どのように工夫すれば良いでしょうか? どなたかご教授をお願いいたします。 #define STRING_NUM 2 /* 文字列の長さ */ int main(void) { int i; int ans = 0; /* 10進数の整数 */ char buf[STRING_NUM]; /* 4進数の文字列 */ buf[0] = '3'; buf[1] = '1'; for ( i = 0 ; i < STRING_NUM; i++ ){ printf(" %c", buf[i]); } printf("\n"); for ( i = 0 ; i < STRING_NUM; i++ ){ if ( buf[i] == '0' ){ ans <<= 2; /* シフトするビット数 */ ans |= 0; } if ( buf[i] == '1' ){ ans <<= 2; ans |= 1; } if ( buf[i] == '2' ){ ans <<= 2; ans |= 2; } if ( buf[i] == '3' ){ ans <<= 2; ans |= 3; } } printf( "ans = %d\n", ans ); return 0; }

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

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.6

この実行環境はなんでしょう? コンパイラはなんでしょう? ・例えば、a*3は、内部では (a << 1) + (a << 0) a*5は (a << 2) + (a << 0) と計算されている可能性が高いです。 ・CPU等の回路構成では、上のような乗算を回路で高速に演算できるようになっています。 ビットシフトを自分で書くより高速でしょう。 ・コンパイラの種類や設定によってできるオブジェクトは変わりますが 乗算はCPUに専用命令があるなら、それを積極的に使おうとするでしょう。 プログラム中でシフト+加算で書いてあったら、乗算に置き換えてくれることはまず無いでしょう。 これが、8bitマイコン用、とかなら、自分でシフト使った方が早いかもしれませんが、PCに入っているようなものだったら、素直に乗算使った方が速いのではないでしょうか

kitten_in_kobe
質問者

お礼

引き続きの回答有り難うございます。 以前、ビットシフトの方が単なる掛け算をするより早いという話を聞いたことがあったので、ずっと今もそういういものだと信じ込んでいました。調べてみると、昔は確かにそうだったようですが、今はKmeeさんがご指摘の通り、大きな差はないようです。 ご指摘ありがとうございました。

その他の回答 (5)

  • nak777r
  • ベストアンサー率36% (49/136)
回答No.5

話の途中で送ってしまいましたが、 言いたい事は、ビットシフトしているから早いのではなく 指定した桁を指定した位置に置いてるだけ 指定した位置にを実現するのにビットシフトを使っているだけです なので、3ビットやら5ビットやらはそもそも 指定した位置に置くだけではそもそも違う値なので ビットシフトでどうにかなるものではないです まぁ2つ一致しない2進数をさらなるビットシフトでどうにか できるのなら話は別ですが、その法則を導き出す なら、演算したほうが早いです。

kitten_in_kobe
質問者

お礼

引き続きの回答有り難うございます。 ビットシフトに意味を、もう1度しっかり理解したいと思います。

  • nak777r
  • ベストアンサー率36% (49/136)
回答No.4

4進数=2進数=10進数 000 = 00-00-00 = 0 001 = 00-00-01 = 1 002 = 00-00-10 = 2 003 = 00-00-11 = 3 010 = 00-01-00 = 4 011 = 00-01-01 = 5 012 = 00-01-10 = 6 013 = 00-01-11 = 7 020 = 00-10-00 = 8 021 = 00-10-01 = 9 022 = 00-10-10 = 10 023 = 00-10-11 = 11 030 = 00-11-00 = 12 031 = 00-11-01 = 13 032 = 00-11-10 = 14 033 = 00-11-11 = 15 100 = 01-00-00 = 16 101 = 01-00-01 = 17 4進数 = 2進数 =10進数 2進数は判りやすいように2桁毎にハイフンで区切って表示してます。 8進数の場合は、3桁区毎にハイフンで区切れば同じような表が出来ます これと同じ表を、3進数で作るとどうなるか 000 = 00-00-00 = 00-00-00 = 0 001 = 00-00-01 = 00-00-01 = 1 002 = 00-00-10 = 00-00-10 = 2 010 = 00-01-00 ≠ 00-00-11 = 3 011 = 00-01-01 ≠ 00-01-00 = 4 012 = 00-01-10 ≠ 00-01-01 = 5 020 = 00-10-00 ≠ 00-01-10 = 6 021 = 00-10-01 ≠ 00-01-11 = 7 022 = 00-10-10 ≠ 00-10-00 = 8 100 = 01-00-00 ≠ 00-10-01 = 9 101 = 01-00-01 ≠ 00-10-10 = 10 102 = 01-00-10 ≠ 00-10-11 = 11 110 = 01-01-00 ≠ 00-11-00 = 12 111 = 01-01-01 ≠ 00-11-01 = 13 112 = 01-01-10 ≠ 00-11-10 = 14 210 = 10-01-00 ≠ 00-11-11 = 15 211 = 10-01-01 ≠ 01-00-00 = 16 212 = 10-01-10 ≠ 01-00-01 = 17 こうなります

kitten_in_kobe
質問者

お礼

回答有り難うございます。 様々な例をお書きくださり、有り難うございました。参考にさせていただきます。

  • m0r1_2006
  • ベストアンサー率36% (169/464)
回答No.3

4倍して,元の数を引けば 3倍になるし, 4倍して,元の数を足せば 5倍になる. 速いかどうかは,分かりかねるが

kitten_in_kobe
質問者

お礼

回答有り難うございます。 確かに、4倍して元の数を引けば3倍になりますね。 ただ、上記のプログラムを活用して、具体的にどうすれば良いでしょうか? お手数をお掛けしますが、教えていただけないでしょうか? よろしくお願いいたします。

  • NNori
  • ベストアンサー率22% (377/1669)
回答No.2

ビットシフトとは、2倍(または1/2)することです。 つまり2回やれば4倍、3回やれば8倍することができます。 逆に言えば3倍や5倍はビットシフトしてもできません。

kitten_in_kobe
質問者

お礼

回答有り難うございます。 やっぱり、ビットシフトを使って3倍や5倍することは原理的に無理なんですね。

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

「ビットシフトを使った方が非常に計算が高速で出来る」って, 本当なの? 3進数や 5進数だと「ビッチシフトだけでは不可能」ってのは理解できてるよね?

kitten_in_kobe
質問者

お礼

回答有り難うございます。 > 3進数や 5進数だと「ビッチシフトだけでは不可能」ってのは理解 > できてるよね? おっしゃる通り、無理だろうと思っていました。しかし、自分の知らない知識を使って工夫すれば可能かもしれないと期待していました。そこで、質問した次第です。

関連するQ&A

  • 10進数を2進数に変換したいのですが・・・

    こんばんは。 入力された10進数を2進数に変換するというプログラムを、一応作成することができたのですが、表示される結果が逆に表示されてしまいます。(例えば、4なら001) どのようにすれば、正しく表示することができるのでしょうか??ちなみにプログラムは #include<stdio.h> int main(void) { int num; printf("数字を入れてください。\n"); scanf("%d", &num); for(num = num ; num>1 ; num = num/2) printf("%d",num%2); printf("%d\n",num); return 0; } です。

  • 16進数から10進数に変換

    いつもお世話になります。 先日バイナリデータを読み込み、ある特定のデータを検索し、 そのデータを10進数に変換する処理がしたいです。 FILE *fp; char buf[1024]; fp = fopen("sample.jpg","rb"); fread(buf, siZeof(char), 1024, fp); for( int i=0; i<1024; i++ ){ if( (buf[i]==0xff) && (buf[i+1] == 0xe0) ){ //※質問詳細下記します。 } } ※ f文で、buf[i+2]buf[i+3]、例えばprintf("%02x,%02x",buf[i+2],buf[i+3]); で出力すると、所望の(11 00 )の16進数で得られています。 このbuf[i+2] buf[i+3]の値を10進数に変換して得るには、 どうしたらいいでしょうか? 0x1100→4352 どうぞよろしくお願い致します。

  • 2進→10進数

    2進数から10進数に変換するプログラムを作りたいんですが #include<stdio.h> main() { int a[8],i=0,ans=0,end; start: printf("2進数を10進数に変換するプログラム\n開始する場合は1を入力終了する場合は0を入力してください。\n"); scanf("%d",&end); if(end==1) { goto s1; } else if(end==0) { goto end; } { s1: for(i=0;i<8;i++) { scanf("%d",&a[i]); } for(i=0;i<8;i++) { a[i]=2^i; } for(i=0;i<8;i++) { ans=ans+a[i]; } printf("二進数"); for(i=8;i<=4;i--) { printf("%d",a[i]); } printf(" "); for(i=4;i<=0;i--) { printf("%d",a[i]); } printf("は%dです。\n",ans); goto start; } end: printf("終了します\n"); } 期待した結果が得られないのですがどこが違っているのか教えていただきたいです、お願いします。

  • お願いします、教えてください。10進数を2進数に変換するには・・・。

    10進数を2進数に変換するプログラムを作成したのですが、うまく動作しません、どうしても解らないので教えてください。 サンプルコードを元に「define」は5で稼動出来る様にしたいのですが、動作せず困っています。以下の、どの部分を修正すれば変換出来るのでしょうか? ご教授よろしくお願いいたします。 //10進数文字を数字の2進数で表示 #include "stdafx.h" #define HEX 5 //「function」:入力文字された文字の処理///////////////////////////////////// char ToInt( char cInt) { int mal=0; switch (cInt){ case '0': mal=0; break; case '1': mal=1; break; case '2': mal=2; break; case '3': mal=3; break; case '4': mal=4; break; case '5': mal=5; break; case '6': mal=6; break; case '7': mal=7; break; case '8': mal=8; break; case '9': mal=9; break; } return (mal); } //「function」:入力文字された文字数//////////////////////////////////////////// char HexInt( char eInt) { char mul=0; switch (eInt){ case 0: mul='0'; break; case 1: mul='1'; break; } return (mul); } //「function」:桁数の計算(10×指数を計算)/////////////////////////////////// int HexAcc( int n ) { int i; int ans=1; for( i=0; i<n; i++ ){ ans *= 10; } return (ans); } int _tmain(int argc, _TCHAR* argv[]) { int i=0,n=0,j=0,s=0,k=0,m=0,e=0,ans=0, add=0; char decimal[255], ditto[255],sub[255],temp[255],chg[255],siu[255]; //入力されない場合// if( 1 > argc ){ } else{ printf("10進数を入力してください。\n"); return 1; } for( k=0; k<255; k++ ){ //文字として'0'を代入// sub[k] = '0'; //subに文字として'0'を代入// temp[k] = '0'; //tempに文字として'0'を代入// chg[k] = '0'; //chgに文字として'0'を代入// siu[k] = '0'; //siuに文字として'0'を代入// } //入力された文字数を受取る// for( i=0; argv[1][i] != '\0'; i++ ){ decimal[i] = argv[1][i]; } decimal[i] = '\0'; //空白文字のチェック// for( i=0; decimal[i] != '\0'; i++ ){ if( decimal[i] != ' ' ){ ditto[n] = decimal[i]; n++; } } //'\0'を代入(文字列の終端)// ditto[n]='\0'; //「0」から「9」のループ// for( n=0; ditto[n] != '\0'; n++ ){ if(( ditto[n] == '0' ) || ( ditto[n] == '1' ) || ( ditto[n] == '2' ) || ( ditto[n] == '3' ) || ( ditto[n] == '4' ) || ( ditto[n] == '5' ) || ( ditto[n] == '6' ) || ( ditto[n] == '7' ) || ( ditto[n] == '8' ) || ( ditto[n] == '9' )){ }else{ printf("エラー\n 10進数を入力してください。\n"); return 0; } } //桁数のループ// for( n=0; ditto[n] != '\0'; n++ ){ m = m + 1 ; } //桁数の判断// if( m <= HEX ){ }else{ printf("エラー\n入力文字数は、%d文字以内にしてください。\n",HEX); return 0; } //subにdittoを代入// for( n=0; ditto[n] != '\0'; n++){ sub[HEX-m+n] = ditto[n]; } sub[HEX] = '\0'; //'\0'を代入(文字列の終端)// //sub[0]からsub[9]の計算// for( n=0; sub[n] != '\0'; n++){ ans = ToInt(sub[n]); add += ans * HexAcc(HEX-n-1); } //2進数の計算・商が0になるまで// for( n=0; sub[n] != '\0'; n++ ){ temp[n] = add % 2; add = add / 2; if( add == 0){ break; } } temp[HEX] = '\0'; //'\0'を代入(文字列の終端)// //桁数のチェック(商・余り)// for( ; n>=0; n-- ){ e = e++; } //temp・値の入替え「tempからchg」// for( n=0; sub[n] != '\0'; n++ ){ chg[HEX-n-2] = temp[n]; } chg[HEX]='\0'; //'\0'を代入(文字列の終端)// //2進数に変換// for( ; n>=0; n-- ){ siu[n] = HexInt(chg[n]); } siu[HEX]='\0'; //'\0'を代入(文字列の終端)// printf("\n10進数文字を2進数で変換した値は・・・ %s \n",siu); }

  • 2進数11111111を-1ではなく256と表示させたい

    #include <windows.h> #include <math.h> CHAR inc2to16(const char *str2inc){ INT i, ans=0; //文字の長さがちょうど8かを調べる if(strlen(str2inc)!=8) return 0; //文字列が1と2で成り立っていない場合0を返す for(i=0 ; str2inc[i]!='\0' ; i++){ if(str2inc[i]!='1' && str2inc[i]!='0'){ return 0; } } //128 64 32 16 8 4 2 1 //文字列を16進数に直し、値を返す for(i=0 ; i<8 ; i++){//8回ループ if(str2inc[i]=='1'){ ans += pow(2, 7-i); } } return ans; } int main(int argc, char *argv[]){ if(argc==1) return 0; printf("%d", inc2to16(argv[1])); return 0; } 01111111 までは127と期待通りの結果が返ってくるのですが、 11111111や11111110 などになると、signed型と判断して、 printf("%d", inc2to16(argv[1]); ではマイナス表示になってしまいます。 %uにしてみても最上位1ビットが1のときは表示がとてつもなく大きくなりますし。。 解決策はありますか?

  • 素数であるかを判断するプログラムについて

    C言語を学習していて「独習C」48ページの次のプログラムが分かりませんでした。 ~~~~~~~~~~~~~~~~ #include <stdlib.h> #include <stdio.h> int main(void) { int num, i, is_prime; printf("判定したい数を入力してください"); scanf("%d", &num); /*ここからがわかりません*/ is_prime = 1; for(i=2; i<=num/2; i=i+1) if((num%i)==0) is_prime = 0; if(is_prime==1) printf("素数です"); else printf("素数ではありません"); return 0; } ~~~~~~~~~~~~~~~ 私はこうなると考えています。どこが間違っているでしょうか? numが0のとき、2<=0となり、素数 numが1のとき、2<=0.5となり、素数でない numが2のとき、2<=1となり、素数でない numが3のとき、2<=1.5となり、素数でない

  • 至急お願いします

    高専生です。 文字列で数字列を入力。 それを実数値に変換し そこから8進数に変換し 再び文字列とて出力したいです。 変換はできているのですが printf("%s",ss)が実行されると 正しい8進数の直後に文字化けまたは 0が出力されてしまい困っています。 例えば10進数の225は8進数では341ですが このプログラムでは出力が341'0'と0が付きます 同様に10進数12345は8進数では30071ですが これでは30071'ヨ@0'と意味不明な文字化けが付きます どうか解決法をご教授ください! 以下自分が組んだプログラム ______________________________________________________ #include<stdio.h> #include<string.h> void main(){ char s[5],ss[100]; int i=0,num=0,keta,hex=0,j=1,cnt1=1,k,x; while(1){ printf("5桁以内の文字列を入力せよ\n"); scanf("%s",&s); keta=strlen(s); //桁をカウントさせる if(keta>5){ printf("文字数不正\n"); } else { break;//条件満たしたら次へ } } while(1){ //桁数から1の倍数の数字を作ります 次のループのギミック j=j*10; cnt1++; if(cnt1>=keta){ break; } } while(1){ if(s[i]=='\0'){ break; } hex=s[i]-'0'; num=num+hex*j; j=j/10; ++i; //文字列で入力されたのを実数に直しました } printf("変換後=>%dです\n",num);//確認用表示 k=keta-1; for(;k>=0;k--){ int x=num%8; ss[k]='0'+x; num=num/8; } s[keta]='\0'; printf("%s%d",ss); ←ここです!!! return; }

  • コマンドライン引数を使って2進数を10進数に変換させたい

    2進数を入力し10進数に変換するプログラムを作成したのですが、うまく動作しないので質問させてください。 コマンドライン引数を使って実行したいのですが2進数も入力出来ず困っています。作成したコードの何処に問題があるのかも解らずにいます。 宜しくお願いします。 作成環境は「Windows XP」「Visual Studio .net 2003」 <作成したコードです> *********************************************************** // binary.cpp : コンソール アプリケーションのエントリ ポイントを定義します。 #include "stdafx.h" #include <stdlib.h> int _tmain(int argc, _TCHAR* argv[]) { if( argc < 8 ){ printf("2進数を入力してください。\n"); exit(1); } //空白文字のチェック// int i=0,n=0; char decimal[ 128 ], binary[ 128 ]; for( i=0; i<argc; i++ ){ if( binary[ i ] != ' ' ){ decimal[ n ] = binary[ i ]; n++; } } //'\0'を代入(文字列の終端)// decimal[ n ]='\0'; //「0」と「1」のループ// for( i=0; i<argc; i++ ){ if(( decimal[ n ] == '0' ) || ( decimal[ n ] == '1' )){ }else{ printf("エラー\n 「0」と「1」以外の文字が入力されております\n"); } } //桁数のループ// int m = 0; for( i=0; i<'\0'; i++ ){ m = m +1 ; } //桁数の判断/// if( m == 8 ){ }else{ printf("エラー\n2進数(0,1)を8桁、入力して下さい。\n"); } //add・初期化// int add = 0; //decimal[0]~decimal[7]の判断// if( decimal[ 0 ] == '1' ){ add += 128; } if( decimal[ 1 ] == '1' ){ add += 64; } if( decimal[ 2 ] == '1' ){ add += 32; } if( decimal[ 3 ] == '1' ){ add += 16; } if( decimal[ 4 ] == '1' ){ add += 8; } if( decimal[ 5 ] == '1' ){ add += 4; } if( decimal[ 6 ] == '1' ){ add += 2; } if( decimal[ 7 ] == '1' ){ add += 1; } //2進数を10進数に変換した値の出力// printf("2進数を10進数に変換した値は %d \n",add); return 0; }

  • 数値を2進数文字列に変換するものなんですが・・・

    数値を2進数の文字列に変換するプログラムを関数として作成しているんですが、わからないことがあるのでお願いします。 char *itob(int value, int size, char binary[]) { int count = 0; /* binaryの添え字 */ int bit = size * 8; /* ビットになおす */ int mask = 1 << bit - 1; /* 先頭ビットに1を立てる */ /* 数値を2進数の文字列に変換する処理 */ do { if(value & mask) { /* valueとmaskのAND(論理積) */ binary[count] = '1';/* '1'を代入 */ }else { binary[count] = '0';/* '0'を代入 */ } value <<= 1; /* valueを左へ1ビットシフト */ count++; /* countを1たす */ }while(count < bit); /* 繰り返しを行う条件 */ binary[count] = '\0'; /* 最後に'\0'を入れる */ return binary; /* 変換した値を戻り値として返す */ } この前にもプログラムがありますが、コンパイルして実行する際に 10001 1110 と入力したら、 11111 という答えを出したいのですが、 これを実行すると、 00000000000000000000000000011111 となってしまいます。 これを11111とするためにはプログラムにどのような処理をすればよいのかわかりませんのでどなたかおわかりのかた解説をお願いします。

  • n進数を10進数に変換するプログラムがわかりません

    整数n(2<=n<=16)とn進数の数字列digitsを与えると10進数に変換して表示するプログラム 関数void base2dec(int n, string digits, int &dec)を使用する 実行例 110101(2)=53 123(8)=83 7ACE(16)=31438 以下はとりあえずつくったみたプログラムです #include<iostream> #include<string> using namespace std; void base2dec(int n, string digits, int &dec) { int i,x=0; for(i=0; i=digits.size()-1; i++) { if(n<10) { x=digits[i]-'0'; } else { x=digits[i]-'A'+10; } dec=(x*n); if(cin >> digits[i++]) { if(n<10) { dec=dec+(digits[i++]-'0'); } else { dec=dec+(digits[i++]-'A'+10); } } } int value = dec; } int main() { int n,value; string digits; cout << "何進数ですか-->"; cin >>n; cout << "数字列を入力してください-->"; cin >>digits;; base2dec(n,digits,value); cout << digits << "(" << n << ")=" << value << endl; return 0; } void関数の中、特に計算方法が間違っていると思うのですが、なにがいけないかわかりません。ちなみにn進数から10進数に直す方法は理解しています。

専門家に質問してみよう