2進数の1の数を数える問題

このQ&Aのポイント
  • 質問者は、与えられた10進数の整数を2進数に変換し、その中の1の個数を数える問題に取り組んでいます。
  • 自分の解答では、10進数を2で割り続けながら余りを計算し、1の個数を数えるアルゴリズムを使用していますが、正しい結果が得られません。
  • 質問者は、どこが間違っているのかわかりませんので、アドバイスを求めています。
回答を見る
  • ベストアンサー

2進数の1の数を数える問題

 次の問題に対して、以下のソースを考案し、実行したところ、以下のようになりました。 【問】 ◆◆◆◆◆  与えられた10進数の整数Nを2進数に変換したときの1の個数を答えよ。  整数の10進数を2進数に変換するには、変換したい10進数を商が0になるまで2で割り続け、求めた余りの部分を逆順に並べる。 例) 13が入力として与えられた場合、以下のように2で割り続け2進数を求める。 13 / 2 = 6 ・・・余り 1 6 / 2 = 3 ・・・余り 0 3 / 2 = 1 ・・・余り 1 1 / 2 = 0 ・・・余り 1  求められたそれぞれの余りを逆順に並べたものが2進数への変換結果となる。  よって入力が13ならば2進数への変換結果は 1101 になり、1は3個あるので出力は3になる。 [入力例1] 13 [出力例1] 3 [入力例2] 45 [出力例2] 4 ◆◆◆◆◆ (自分の解答、□はタブ) ◆◆◆◆◆ #include <stdio.h> #include <stdlib.h> /* EXIT_SUCCESS */ int main(void) { □int n, bit, s; □scanf("%d", &n); □ □bit = n % 2; □n /= 2; □s = 0; □while(n) { □□if (bit) □□□s++; □bit = n % 2; □n /= 2; □} □printf("%d", s); □return EXIT_SUCCESS; } ◆◆◆◆◆ (実行結果1) ◆◆◆◆◆ [入力] 13 [出力] 2 ◆◆◆◆◆ (実行結果2) ◆◆◆◆◆ [入力] 45 [出力] 3 ◆◆◆◆◆ となり、正解となりません。  自分の考えとしては、入力された数値を変数nに収め、これをどんどん2で割っていき、そのときの余り(0か1)を変数bitに収めていき、nが0になるまで処理を繰り返し、bitが0でないとき、変数s(初期値0)に1ずつ加算していき、最後にsを出力する、という方針です。  初期値の設定辺りが間違っているのだと思いますが、これ以上いくら考えても正解が得られません。どこがどう間違っているのでしょうか。どなたかご教授頂きたく、お願い致します。

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

  • ベストアンサー
  • maiko0318
  • ベストアンサー率21% (1483/6970)
回答No.2

惜しい。これが正解。 #include <stdio.h> #include <stdlib.h> /* EXIT_SUCCESS */ int main(void) { □int n, bit, s; □scanf("%d", &n); □ □s = 0; □while(n) { □□printf("%d/2=%d・・・余り%d\n",n,n/2,n%2); □□bit = n % 2; □□n /= 2; □□if (bit) □□□s++; □} □printf("%d", s); □return EXIT_SUCCESS; } ヒントとして途中経過を表示しているから考えてみてください。

その他の回答 (3)

  • Ogre7077
  • ベストアンサー率65% (170/258)
回答No.4

ループ処理に失敗していますね 同様の処理を二箇所に分けているのも感心しません。 あと最近のコンパイラなら自動的に最適化してくれますが、 二進数の処理をするなら、やはりビット演算で書くのが筋でしょう。 // 正解例 ただし入力値が正の整数の場合のみ int s, b; for (s = 0, b = 入力値; b != 0; b >>= 1) { □ if(b & 1 > 0) s++; } printf("%d is %d\n", 入力値, s); -- 出題の例からは外れますが、別解として // K&R に登場する高速化した処理 int s, b; for (s = 0, b = 入力値; b != 0; s++) { □ b &= b - 1; } printf("%d is %d\n", 入力値, s); // 分割統治法を用いた実用的な処理 unsigned int t = 入力値; t -= (t >> 1) & 0x55555555; t = (t & 0x33333333) + ((t >> 2) & 0x33333333); t = (t + (t >> 4)) & 0x0f0f0f0f; t += t >> 8; t += t >> 16; t &= 0x3f; printf("%d is %d\n", 入力値, t);

  • LunaSun
  • ベストアンサー率30% (4/13)
回答No.3

みんな、do~whileを忘れないであげてね。 #include <stdio.h> #include <stdlib.h> /* EXIT_SUCCESS */ int main(void) { □int n, bit, s; □scanf("%d", &n); □s = 0; □do { □□s += n % 2; □} while ((n /= 2)); □printf("%d\n", s); □return EXIT_SUCCESS; }

  • dolittle0
  • ベストアンサー率26% (11/42)
回答No.1

while ループの後に、if(bit) s++; を追加すればいいと思います。

awa3yee
質問者

お礼

 ありがとうございます。

関連するQ&A

  • 10進数→2進数の出力について

    コマンドライン引数から10進数の値を入力して 2進数に変換して出力しようとしています。 ※入力される10進数の値はかなり大きなものを想定しています。 現在は下記のようなコードで変換しようとしていますが失敗しています。 動作環境は『WindowsXP、Activeperl-5.12.4.1205』です。 拙い説明ですが、よろしくお願いいたします。 # コマンドライン引数は「9223372036854775808」 $n = unpack("B8", pack("C", $ARGV[0])); print n; # 実行結果は「11111111」 # 期待している出力結果は「1000・・・000」(←0が64個) 9223372036854775808

    • ベストアンサー
    • Perl
  • C言語 10進数→2進数

    キーボードで入力された1以上の正の整数n(1~15)を2進数(4bit)で出力するプログラムを作りたいんですが、 出力例に書かれている内容、 -出力例- 正の整数:12 整数 12 を2進数表記すると下位bitより 0011 となります。 ---- 上記の下位bit、というのはどういう意味でしょうか? また、この下位bitというものをどうやってプログラム上で 表記すればいいのでしょうか? 教えてください。

  • おしえてください5

    main関数内でchar型の変数word[20]を宣言し,scanfを用いて文字列を入力する. 再帰呼び出しでword内の文字列を逆順に表示する関数call_nextを作製し, 入力した文字列を逆順に表示せよ. ※グローバル変数は用いないこと.グローバル変数を用いた場合は0点とする. ※通常scanfではスペースは読み込めないが  scanf(" %[^\n]", str);  とすることで,スペースも読み込みができる. <実行結果例1> Input word(20). -> society society yteicos <実行結果> Input word(20). -> RATS & STAR RATS & STAR RATS & STAR

  • 2進数を10進数にするプログラム作成について

    10進数から2進数に変換するプログラムはできたのですが2進数から10進数に変換するプログラムが作れません。。 値を入力してください:1111←と入力(例) 10進数では15です。 もう一度実行しますか?(1…yes/2…no) というプログラムを作ろう思っています。 うまく作れずエラーばかり起きてしまいます。 どうか教えて下さい。お願いします。

  • 文字数の逆順

    C++で入力文字の文字数を関数を使って逆順にするにはどのようなプログラムを作ればよいでしょうか。 入力文字がabcd 文字数4個 4321と出力したい。

  • 8桁の2進数を10進数に変換する方法を教えてください。

    キーボードから2進数を入力した値を10進数に変換し、変換結果を出力する方法が解りません。作成するにあたり仕様があり、私一人では解決できないので相談させていただきました。 <仕様は以下の通りです> (1)このプログラム(8桁の2進数を10進数に変換)をする際は、最後に出力する時(printf)以外は関数を使ってはいけません。 (2)キーボードから2進数を入力させる。 (3)空白(ブランク)が入力されても変換可能にする。 (4)入力された2進数は8桁にし、8桁以上の場合はエラーを出す。 (5)2進数の「0」と「1」以外の文字が入力された場合はエラーを出す。 (6)バイナリ変換をし、変換結果を出力する。 以上になります。 まだ、C言語を勉強を習い始めの初心者です。どうか、ご回答のほど宜しくお願いします。

  • アルゴリズム

    教えてください。 フローチャート作成 入力された10進の自然数xを2進数yに変換し出力するプログラムのフローチャートをサブルーチンも含めて全て書け。ただし、整数型の変数aから第iビット目(最初を下位ビットとして第0ビットとせよ)を取り出す整数型関数(メソッド)get_bit( a,i )を作成すること。 プログラム作成 上で設計したプログラムを作成する。 実行結果 上で作成したプログラムの実行し、その実行結果を示す。

  • フローチャートお願いします!!!!!

    問題1 入力された10進数の自然数Xを2進数yに変換し出力するプログラムのフローチャートをサブルーチンを含めてすべてかけ。しかし、整数型の変数aから第iビット目(最初を下位ビットとして第0ビットとせよ)を取り出す整数型関数(メソッド)get_bit(a,i)を作成すること。 これのプログラムの作成ができません。お願いします。returna&(1<<n)を使えば大丈夫と思いますが、なかなかうまくできません。JAVAで簡単にわかりやすくすべて書いてください。 問題2 キーボードから自然数nを入力し、1からNまでの和を求め、出力するプログラムのフローチャートをサブルーチンも含めてかけという問題です。これもJAVAでお願いします。

  • 8進数と16進数で表示するプログラム

    int型変数bに10進数として数値を入力し、その値を実行結果のように8進数と16進数で表示するプログラムを作成しなさい という問題にとりかかっているのですが、いまいち理解できません scanfで値を入力させる項目は必要とわかるのですが、その他がどうしてもわかりません、ご教授して頂ければ幸いです

  • 入力した任意の数の平方根を求める

    C言語を少しずつですが勉強していて、最小値から最小値までの和を求めるのと、入力した数の2乗を求めるプログラムはわりと楽に完成したのですが、平方根を求めるというのができずに困っています。 プログラムの流れを説明すると、 1.どの処理を行うのか、数字+Enterで選択(平方根は、case 3です) 2.その処理を行う 3.結果の出力 です。 平方根の処理は、 scanfで実数を変数に代入→計算を行う関数を実行→結果を出力です。 症状としては、例えば4と入力して処理を実行すると、桁数のすごく大きい数が入力した数として処理され、また平方根も正しく求められていないようです。 (コンパイル時にエラーは出ていません)