質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

8回答

1752閲覧

入力されたn以下で最大の2のべき乗

ta-9

総合スコア11

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

1グッド

1クリップ

投稿2020/04/26 06:44

###やりたい事
0以上で2147483648未満のnを読み取った後に、n 以下の最大の2のべき乗を計算して出力する。
###注意
読み取ったnが0 の時は0を出力。

c

1#include<stdio.h> 2int main(void){ 3 4 5long int n; 6long int b; 7 8scanf("%ld", &n); 9//計算はfor文? 10for(nが231乗以下を確認?) 11//どうやってn以下の最大の2のべき乗を毎回確認するのか...? 12... 13 14if(n==0){ 15 k=n; 16 } 17 18printf("%ld\n", b); 19 20return 0; 21}
DrqYuto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答8

0

ベストアンサー

C

1 2#include<stdio.h> 3int main(void) { 4 5 long int n; 6 long int b; 7 int t; 8 9 scanf("%ld", &n); 10 11 t = 0; 12 for ( b = 1L; b*2L <= n; b *= 2L ) { 13 ++t; 14 } 15 printf("2^%d = %ld (< %ld)\n", t, b, n); 16 17 return 0; 18}

投稿2020/04/26 07:00

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ta-9

2020/04/26 07:28

ご回答有難うございます。 シンプルでとても分かりやすかったのでベストアンサーにさせて頂きます。
raccy

2020/04/26 07:44

ベストアンサーを決めるのはいいですが、32bit環境またはWindowsの64bit環境で2147483647を入力したときにどのようになるかぐらいは確認してから提出した方がいいですよ。
kazuma-s

2020/04/27 05:35 編集

n が 1073741824~2147483647 のとき正しく動かないコードがなぜベストアンサーなんだろう。long が 64ビットの環境でしか確かめていないのだろう。
katoy

2020/05/03 12:07

> ... 正しく動かないコードがなぜベストアンサーなんだろう .... ベストアンサーを決めるのは 質問者です。 問題解決ができなかった人は、その問題の細かな点 / 微妙な点を理解できていないわけです。 お宝鑑定で、持ち主と専門家での評価が大きく異るのことが多いのと似たような状況なのだと思います。
guest

0

long int で扱う, unsigned long int で扱う、
上位側から 1 が立っている最初のビットを探す、下位がわから 1 が立っている最後のビットを探す
の方法の組み合わせの 4つのメソッドを書いてみました。
x.c

c

1#include<stdio.h> 2#include <limits.h> 3#include <stdlib.h> 4 5long int get_largest_2pow_0(long int n) { 6 if (n == 0) { 7 return 0; 8 } 9 long int ans = 1; 10 while (ans > 0 && ans <= n) { 11 ans = ans << 1; 12 } 13 return labs(ans / 2); 14} 15 16 17long int get_largest_2pow_1(long int n) { 18 if (n == 0) { 19 return 0; 20 } 21 long int ans = -1; 22 while (ans & n) { 23 ans = ans << 1; 24 } 25 return -(ans >> 1); 26} 27 28long int get_largest_2pow_u0(unsigned long int n) { 29 unsigned long int ans = 1L; 30 while (ans <= n) { 31 ans = ans << 1; 32 } 33 return ans >> 1; 34} 35 36long int get_largest_2pow_u1(unsigned long int n) { 37 if (n == 0) { 38 return 0; 39 } 40 unsigned long int ans = ~0; 41 while (ans & n) { 42 ans = ans << 1; 43 } 44 return (~ans >> 1) + 1; 45} 46 47int main(void) { 48 long int data[] = { 49 // -1, 50 0, 51 1, 2, 3, 4, 5, 7, 8, 9, 52 (1 << 7) - 1, 1 << 7 , (1 << 7) + 1, 53 (1 << 15) - 1, 1 << 15, (1 << 15) + 1, 54 2147483646, 2147483647, 55 LONG_MAX - 1, LONG_MAX 56 }; 57 58 for(int i = 0; i < sizeof(data) / sizeof(long int); i++) { 59 long int num = data[i]; 60 printf("%ld -> %ld, %ld, %ld, %ld\n", 61 num, 62 get_largest_2pow_0(num), get_largest_2pow_1(num), 63 get_largest_2pow_u0(num), get_largest_2pow_u1(num)); 64 } 65 return 0; 66}

実行例:

イメージ説明

このコードでは いずれも 順番にビットをしらべています。
(0x1, 0x10, ... 0x10000000) のテーブルを用意して、2分法で 最上位のビット1を探すという方法もありかもしれません。(数をあてるHight & low ゲームみたいに)

でも ビット演算にはとんでもないテクニックがいろいろあります。
質問文の問題は 左からビットみていったとき 最初に 1 が現れる位置をもとめることと同じです。
興味があれば、こういった方法も研究してみるとう良いです。下の参考情報ページなどを読んでみてください。

参考情報

  • データ型の最大値と最小値の一覧【32/64bit環境 limits.h/stdint.h】

https://marycore.jp/prog/c-lang/data-type-min-max-values/

  • ビット演算あれこれ

http://marupeke296.com/TIPS_No17_Bit.html

  • de Bruijn sequenceを用いたLSB/MSB位置検出テクニック

https://onihusube.hatenablog.com/entry/2019/09/20/230416

  • ++11で実装するNTZとNLZ

https://qiita.com/kazatsuyu/items/38203287c19890a2b7c6

投稿2020/04/26 22:22

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

C

1#include <stdio.h> 2#include <stdint.h> 3#include <inttypes.h> 4 5int main(void) 6{ 7 uint_fast32_t n; 8 if (scanf("%" SCNuFAST32, &n) != 1 || n >= (1ul<<31)) return 1; 9 uint_fast32_t x = 1; 10 while (x <= n) x *= 2; 11 printf("%" PRIuFAST32 "\n", x / 2); 12 return 0; 13}

投稿2020/04/26 07:18

raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

プログラミング以前の問題です。

どうやったら解けるか、もちろんコンピュータに解かせるのに適した解法というのもありはしますが、まずは「数学」(あるいは算数)の問題として日本語と数式で解き方を考えてからそれをプログラムに落とし込みましょう。

(「プログラミング言語で考える」なんてのは相当に非人間的作業です。出来なくて当然。)

2を底とする対数の整数部を求める、なんていう手法もありかなぁ...今回は前の質問より桁数が少ないから、コンピュータでの実現にも気を使わない。

ところで、nは整数、とか勝手に決めちゃっていいんでしょうか?

投稿2020/04/26 07:07

thkana

総合スコア7639

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

coco_bauer

2020/04/26 08:10

2を底とする対数の整数部を求める、というのが素直な解法のように思います。 ”2を底とする対数を求める”、"その整数部を求める"はプログラム言語で記述すれば良いので。 「nは整数、とか勝手に決めちゃっていいんでしょうか」 <- nは、”scanf("%ld", &n);”で値が入れられているので、整数でしょう。  nが0以下の整数の場合は”解無し”になってしまうので、チェックは必要ですが。
thkana

2020/04/26 09:46 編集

> nは、”scanf("%ld", &n);”で値が入れられているので、整数でしょう。 そのコードがどういうものか、なんの説明もないんですよね。出題者が提示したものか、それとも先輩から引き継いだ「遺産」なのか。まえの平方根の問題では、なぜかいくつかの質問が、何年かに渡って(int)sqrt(x);ってなコードを書いていたりしたし。ということで、書いてあるコードは「不明」なので無視しています。 > nが0以下の整数の場合は”解無し”になってしまう そちらは、nは0以上、とnが0のときは0を返すとの説明があるので。
guest

0

解決済みですが、再帰関数で書いてみました。動作未確認。

C

1unsigned int largetstPowerOf2(unsigned int n) 2{ 3 //nがゼロの場合は答えが存在しないので、nは1以上とします。 4 return (1 == n) ? 1 : largestPowerOf2(n >> 1) << 1; 5}

投稿2020/05/03 12:14

編集2020/05/03 12:20
HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

C

1#include <stdio.h> 2 3int main(void) 4{ 5 int n; 6 scanf("%d", &n); 7 n |= (n >> 1); 8 n |= (n >> 2); 9 n |= (n >> 4); 10 n |= (n >> 8); 11 n |= (n >>16); 12 n -= (n >> 1); 13 printf("%d\n", n); 14}

別解

C

1#include <stdio.h> 2 3int main(void) 4{ 5 int n; 6 scanf("%d", &n); 7 while (n & n-1) n &= n-1; 8 printf("%d\n", n); 9}

投稿2020/04/26 17:29

編集2020/04/26 19:23
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

C

1#include <stdio.h> 2#include <inttypes.h> 3int main(void){ 4 5 6 uint32_t n; 7 uint32_t b; 8 9 scanf("%"PRId32, &n); 10 b=n; 11 b = (b & 0xFFFF0000) ? (b & 0xFFFF0000) : b; 12 b = (b & 0xFF00FF00) ? (b & 0xFF00FF00) : b; 13 b = (b & 0xF0F0F0F0) ? (b & 0xF0F0F0F0) : b; 14 b = (b & 0xCCCCCCCC) ? (b & 0xCCCCCCCC) : b; 15 b = (b & 0xAAAAAAAA) ? (b & 0xAAAAAAAA) : b; 16 17 18 printf("%"PRId32"\n", b); 19 20 return 0; 21}

投稿2020/04/26 07:29

ozwk

総合スコア13521

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

2のべき乗を算出し、nと比較すればいいんでは

投稿2020/04/26 06:47

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問