何ビットで収まるのか


52

正の32ビット整数(1 ≤ n ≤ 0xFFFFFFFF)出力の場合、その整数を表すのに必要なビット数。

テストケース

| n    | n in binary | bits needed |
|----------------------------------|
| 1    | 1           | 1           |
| 2    | 10          | 2           |
| 3    | 11          | 2           |
| 4    | 100         | 3           |
| 7    | 111         | 3           |
| 8    | 1000        | 4           |
| 15   | 1111        | 4           |
| 16   | 10000       | 5           |
| 128  | 10000000    | 8           |
| 341  | 101010101   | 9           |

4294967295 => 11111111111111111111111111111111 => 32

だからf(16)印刷するか、戻ります5

これはです。バイト単位の最短コードが勝つ


2
これは、2を底とする対数の上限です。
orlp

23
@orlp実際はfloor(log2(num))+1
Kritixi Lithos

2
@KritixiLithosそうです。
orlp 16

3
気にせずnum、2のべき乗の場合に区別が重要であることに気付きました。
ブライアンJ

11
これは、多くの些細な解決策を伴う些細な課題です。ただし、いくつかの重要なソリューションもあります。投票者へ:組み込み関数を支持する前に、このメタ投稿の最初の文を読んでください。(このコメントから謙虚に撮影)
Kritixi Lithos

回答:



35

JavaScript(ES6)、18バイト

f=n=>n&&1+f(n>>>1)
<input type=number min=0 step=1 value=8 oninput="O.value=f(this.value)">
<input id=O value=4 disabled>


これは、ここで数少ない重要なソリューションの1つです。素晴らしい戦術!
Kritixi Lithos

1
n>>>1サポートするべきn > 0x7FFFFFFFですか?
アーナルド

@Arnauldうーん、その高さに>>失敗したnとは知りませんでした。ありがとう。
ETHproductions 16

ニース、私の最初の試みはf=(a,b=1)=>a>1?f(a>>1,++b):b
Bassdrop Cumberwubwubwub

28

x86アセンブリ、4バイト

定数を想定EBX

bsr eax,ebx
inc eax

EAXには、定数に必要なビット数が含まれています。

バイト: ☼¢├@

16進数: ['0xf', '0xbd', '0xc3', '0x40']


2
実際の8バイトコンパイルされたx86アセンブリコードの16進ダンプを含めてください。
Loovjo

そうでした。そして、私は間違いを犯したことに気付いたので、ありがとう。ルールに合わせて「inc eax」を追加しました。バイトを失いました。:(
z0rberg's

私の投稿を適切なフォーマットに変更しました。それを修正してくれてありがとう!
z0rbergの

2
ところで、Assemblyのサブミットでは、入力が特定のregisterに既に保存されていると想定できるため、そのようにして数バイトを削ることができると思います。
Loovjo

1
アセンブリの送信を、アセンブリ言語のソースコードではなく、コンパイルされたマシンコードのバイト数としてカウントするのが慣習ですか?
smls

18

Python、14バイト

int.bit_length

オンラインでお試しください!


Python 2でも機能します。
vaultah

1
確かにそうです。Python 2のintは32ビットではなく64ビット幅でした。
デニス

Python 3 bit_lengthbit_length()です。
dfernan 16

2
@dfernanこれは関数呼び出しではありません。それは機能です。もしn個であるint型int.bit_length(n)およびn.bit_length()正確に同じことを行います。
デニス

2
@dfernan int.bit_length(n)は関数呼び出しであるため、入力が変数に格納されていることを前提とするスニペットです。これはルールで許可されていないため、追加(n)するとこの回答が無効になります。ただし、int.bit_length関数に評価され、後で使用するために変数に保存できます。これはデフォルトで許可されています。
デニス

15

ラビリンス13 12バイト

 ?
_:
2/#(!@

オンラインでお試しください!

説明

プログラムは、入力がゼロになるまで入力を単純に繰り返し2で除算します。ステップ数は、各ステップで値を複製することにより追跡されます。ゼロになったら、スタックの深さ(マイナス1)を出力します。

プログラムは?、入力を読み取るから始まります。メインループは下の2x2ブロックで、反時計回りに移動します。

:   Duplicate current value.
_2  Push 2.
/   Divide.

完全な反復の後、値がゼロになると、最後の線形ビットが実行されます。

#   Push stack depth.
(   Decrement.
!   Print.
@   Terminate.

5
このソリューションは完全です-入力を受け取り、回答を提供し、この特定の目的のために既存の関数を使用しません-回答を手動で計算します。私にとって、これは他のほとんどの答えよりもゲームの精神にあります。
ヨハン

15

C、31バイト

f(long n){return n?1+f(n/2):0;}

...その後、再帰について考えました。あいまいなものから明白なものまで、長さの4分の1が落ちました。

Coliruでライブを見る


C、43バイト

c;
#define f(v)({for(c=0;v>=1l<<c;++c);c;})

符号なしの値(例:)で呼び出すfと、ビット長が「戻り」ます。でも動作します!f(42u)0u

ゴルフのない説明:(バックスラッシュは省略)

c;
#define f(v)
    ({ // GCC statement-expression

        // Increment c until (1 << c) >= v, i.e
        // that's enough bits to contain v.
        // Note the `l` to force long
        // arithmetic that won't overflow.
        for(c = 0; v >= 1l << c; ++c)
            ; // Empty for body

        c; // Return value
    })

Coliruでライブを見る


OPはn> = 1を保証するため、n?...:0必要ありません。
マッド物理学者

1
@MadPhysicistよく私はどこかに再帰を停止する必要があります、私はしないでください;)
クエンティン

OIC。注意深く読んでおらず、今は馬鹿げているように感じます。どちらの方法でもきちんと答えます。
マッド物理学者

@MadPhysicist心配無用、ありがとうございました:)
クエンティン

gccステートメント式を想定した非再帰的なソリューションについては、この#define f(n) ({64-__builtin_clzl(n);})アプローチも使用する傾向があると思われます。
モアレキ




12

網膜56 37バイト

このソリューションは、必要なすべての入力値で機能します。

Retinaがこの課題で直面する最大の問題は、文字列の最大長が2 ^ 30文字であるため、数値(単項表現)を扱う通常の方法は2 ^ 30を超える値では機能しないという事実です。

この問題を解決するために、数値の一種の10進数表現を維持しながら別のアプローチを採用しましたが、各桁は単項で記述されています(この表現をdigitunaryと呼びます)。たとえば、数字341は数字のように書かれ111#1111#1#ます。この表現を使用して、最大2^30/10桁数(最大1億桁)の数字を処理できるようになりました。任意の算術演算では標準の単項式ほど実用的ではありませんが、少しの努力であらゆる種類の演算を行うことができます。

注:理論上、桁数は他の基数を使用できます(たとえば、バイナリ1101#1##基数2の桁数になります)が、Retinaには10進数と単項を変換する組み込み関数があり、他の基数を直接処理する方法がないため、10進数がおそらく最も扱いやすい基数です。

私が使用したアルゴリズムは、ゼロに達するまで2で連続した整数除算を行います。除算の数は、この数を表すのに必要なビット数です。

それでは、どのように数字を2で割るのでしょうか?これを行うRetinaスニペットを次に示します。

(1*)(1?)\1#        We divide one digit, the first group captures the result, the second group captures the remainder
$1#$2$2$2$2$2      The result is put in place of the old number, the remainder passes to the next digit (so it is multiplied by 10) and is divided by two there -> 5 times the remainder goes to the next digit

この置換は、桁数を2で割るのに十分であり、元の数が奇数の場合、末尾から.5を削除するだけです。

したがって、完全なコードは次のとおりです。数字に数字が残るまで2で除算しn、各反復で文字列の前にリテラルを配置しますn。最後の数字が結果になります。

.                  |
$*1#               Convert to digitunary
{`^(.*1)           Loop:|
n$1                    add an 'n'
(1*)(1?)\1#            |
$1#$2$2$2$2$2          divide by 2
)`#1*$                 |
#                      erase leftovers
n                  Return the number of 'n's in the string

オンラインでお試しください!


更新されたソリューション、37バイト

マーティン・エンダーのおかげで、長さの約3分の1をゴルフした多くの良いアイデアによる大きなリファクタリング!

主なアイデアは_、単項記号として使用することです。この方法では、文字列に通常の数字を使用できます。_では、必要なときに sに使用できます:これにより、分割および複数の挿入時に多くのバイトを保存できます桁。

コードは次のとおりです。

<empty line>    |
#               put a # before each digit and at the end of the string 
{`\d            Loop:|
$*_                 Replace each digit with the corrisponding number of _
1`_                 |
n_                  Add an 'n' before the first _
__                  |
1                   Division by 2 (two _s become a 1)
_#                  |
#5                  Wherever there is a remainder, add 5 to the next digit
}`5$                |
                    Remove the final 5 you get when you divide odd numbers
n               Return the number of 'n's in the string

オンラインでお試しください!


1
私は同様の数値形式を使用しました(ただし、単項コード化された10進数と呼びます)。
トビースパイト


10

Jolf、2バイト

lB

バイナリに変換してから長さを見つけてください。



10

JavaScript ES6、19バイト

a=>32-Math.clz32(a)

Math.clz32数値の32ビットバイナリ表現の先行ゼロビットの数を返します。必要なビット数を取得するために必要なことは、32からその数を減算することだけです

f=
  a=>32-Math.clz32(a)
  
pre {
    display: inline;
}
<input id=x type="number" oninput="y.innerHTML = f(x.value)" value=128><br>
<pre>Bits needed: <pre id=y>8</pre></pre>


2
代替a=>1+Math.log2(a)|0も19バイトです。
ニール

5
@Neil 1+...|0チルドを引いて悲鳴を上げる!a=>-~Math.log2(a)18
edc65 16

@ edc65 17を数えます...しかし、はい、私は何かを失っていると確信していました、それを指摘してくれてありがとう。
ニール

@Neil個別の回答として自由に投稿してください。それは不公平感じるだろうので、それは減少したバイト数のためのあなたの使用して私の答えとは異なる方法を使用しています
Bassdrop Cumberwubwubwub

10

bash / Unixツール、16バイト

dc<<<2o$1n|wc -c

これをスクリプトに保存し、入力を引数として渡します。その数をバイナリで表すのに必要なビット数が出力されます。

説明は次のとおりです。

dcはスタックベースの計算機です。トークンに解析される入力は次のとおりです。

2 —スタックで2を押します。

o —スタック(2)から値をポップし、それを出力ベースにします(したがって、出力はバイナリになります)。

bashプログラムへの引数の値($ 1)—その引数をスタックにプッシュします。

n —スタック(値は入力番号)から値をポップし、末尾の改行なしでそれを出力します(出力ベースであるため、バイナリで)。

したがって、dcコマンドは、数値をバイナリで出力します。

dcの出力は、-cオプションを使用してコマンドwcにパイプされ、入力の文字数が出力されます。

最終結果は、引数のバイナリ表現で桁数を出力することです。


良い言語の選択ですが、説明を含めればもっとクールになります。
NH。

@NHありがとう。説明を追加しました。
ミッチェルスペクター

9

Googleスプレッドシート、15バイト

セルから入力A1を取得し、式を保持するセルに出力します

=Len(Dec2Bin(A1

または

=Int(1+Log(A1,2

または

=Int(Log(2*A1,2

Excel、17バイト

上記と同じですが、MS Excel用にフォーマットされています

=Len(Dec2Bin(A1))

または

=Int(1+Log(A1,2))

または

=Int(Log(2*A1,2))


8

ゼリー、2バイト

BL

バイナリに変換し、長さを見つけます。


8

C#、63 45 31バイト

LoovjoとTuukkaXのおかげで18バイト節約

Graxのおかげで14バイト節約

 b=>1+(int)System.Math.Log(b,2);

10進数nには⌊log2(n)⌋+ 1ビットが使用されます。 ます。これこのページでます。

特定の10進整数のビット数

2 ^(b-1)≤n≤2 ^ b – 1の場合、正の整数nはbビットを持ちます。次に例を示します。

  • 16≤29≤31、または2 ^ 4≤29≤2 ^ 5 – 1のため、29には5ビットがあります。
  • 64≤123≤127、または2 ^ 6≤123≤2 ^ 7 – 1であるため、123には7ビットがあります。
  • 512≤967≤1023、または2 ^ 9≤967≤2 ^ 10 – 1であるため、967には10ビットがあります。

数値が大きい場合は、2のべき乗の表を参照して、数値を含む連続した累乗を見つけることができます。

これが機能する理由を確認するには、たとえば、整数2 ^ 4〜2 ^ 5 – 1のバイナリ表現を考えてください。それらは10000〜11111であり、すべての可能な5ビット値です。

対数を使用する

上記の方法は、別の言い方をすることもできます。ビット数は、自分の数よりも大きい最小の2のべき乗の指数です。次のように数学的に述べることができます。

bspec =⌊log2(n)⌋+ 1

その式には3つの部分があります。

  • log2(n)は、nの2を底とする対数を意味します。これは、nを取得するために2を累乗する指数です。たとえば、log2(123)≈6.9425145です。小数部の存在は、nが2の累乗の間にあることを意味します。

  • xは、xの整数部分であるxの底です。たとえば、⌊6.9425145⌋= 6です。⌊log2(n)⌋は、nのバイナリ表現で2のべき乗の指数と考えることができます。

  • +1は、指数を次に高い2のべき乗にします。このステップは、2進数の2 ^ 0桁を考慮し、合計ビット数が得られると考えることができます。この例では、6 + 1 = 7です。天井関数—⌈xceiling(x以上の最小整数)を使用して、ビット数を計算することができます。

bspec =⌈log2(n)⌉

ただし、nが2のべき乗の場合、これは失敗します。


そこに余分なスペースがあります...)+ 1)...-> ...)+1...。また、値を印刷する代わりに直接返すことができると思います。
Loovjo

あなたは行って、31にそれをドロップダウンすることができますb=>1+(int)System.Math.Log(b,2); Math.Floorと同じ出力を提供int型の変換を、あなたは一度だけのシステムを参照する場合は、usingステートメントを必要としません。
Grax32 16

6

C#、32バイト

n=>Convert.ToString(n,2).Length;

パラメータをバイナリ文字列に変換し、文字列の長さを返します。


4

Haskell、20バイト

succ.floor.logBase 2

2を底とする対数を取り、1を加算する関数を作成します。


4

Befunge-9323の 21バイト

&>2# /# :_1>+#<\#1_.@

Befungeは2Dグリッドベースの言語です(ただし、1行しか使用していません)。

&                      take integer input
 >2# /# :_             until the top of the stack is zero, halve and duplicate it
          1>+#<\#1_    find the length of the stack
                   .@  output that length as an integer and terminate the program

オンラインでお試しください!


@JamesHoldernessありがたいことに、ハッシュ/スペースが非常に多いので短縮できると思ったが、手に入れることができなかった。
JayDepp 16





3

QBIC、18バイト

:{~2^q>a|_Xq\q=q+1

それはすごいマイクです!しかし、それはどのように機能しますか?

:        Read input as integer 'a'
{        Start an infinite DO-LOOP
~2^q>a   If 2 to the power of q (which is 1 by default) is greater than a
|_Xq     Then quit, printing q
\q=q+1   Else, increment q
[LOOP is closed implicitly by QBIC]


3

オクターブ、19バイト

@(x)nnz(dec2bin(x))    % or
@(x)nnz(de2bi(x)+1)    % or
@(x)nnz(de2bi(x)<2)    % or
@(x)numel(de2bi(x))    % or
@(x)rows(de2bi(x'))

Octaveには、10進数を2進数に変換するための2つの関数があります。

dec2bin数値を文字の文字列10(ASCII値4849)に変換します。文字列の長さは、特に指定がない限り、必要なビット数に等しくなります。文字10はゼロではないnnzので、次のような要素の数を見つけるために使用できます@(x)nnz(dec2bin(x))。これは19バイトなので、Luis Mendoの他のOctaveの回答と結びついています

を使ってもっとうまくやれますde2biか?

de2biは、2進数を文字ではなく、数値10整数のベクトルとして返す関数です。de2biは明らかに2バイト短いですがdec2bin、もう使えませんnnz。私たちはすることができます使用しnnz、我々はどちらか追加した場合1、すべての要素に、または唯一の論理ベクトルにそれを作るtrueの値。@(x)nnz(de2bi(x)+1)そして@(x)nnz(de2bi(x)<2)両方とも19バイトです。を使用numelすると19バイトも得られますが、@(x)numel(de2bi(x))

rowsは1バイトより短いですnumelde2bi、水平ベクトルを返すため、転置する必要があります。@(x)rows(de2bi(x)')ちょうど19バイトにもなります。



2

網膜 44  23バイト

入力値が大きい場合、実行するにはメモリが多すぎます。単項に変換してから、2で除算を繰り返し、ゼロに達するまで何回かをカウントします。バイトカウントはISO 8859-1エンコードを前提としています。

.*
$*
+`^(1+)1?\1
$1_
.

オンラインで試す


1
これが有効かどうかわかりません。これは「おそらくあなたが持っているよりも多くのメモリを必要とする」というケースではありませんが、「Retina自体が処理できるよりも多くのメモリを必要とします」特に、Retinaの実装の制限により、オーダー2 ^ 30以上の入力では、単項への初期変換は失敗します。
マーティンエンダー

:それが有効である場合、それはかかわらず、多くを短縮することができtio.run/nexus/retina#@6@nxaWixaWdEKdhqK1paB9jyKViGM@l9/@/saUhAA
マーティン・エンダー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.