In wie viele Bits passe ich?


52

Geben Sie für jede positive 32-Bit-Ganzzahl ( 1 ≤ n ≤ 0xFFFFFFFF) die Anzahl der zur Darstellung dieser Ganzzahl erforderlichen Bits aus.

Testfälle

| 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

So f(16)würde drucken oder Rückkehr5

Das ist . Kürzester Code in Bytes gewinnt


2
Dies ist die Obergrenze des Logarithmus zur Basis 2.
Orlp

23
@orlp Es ist eigentlichfloor(log2(num))+1
Kritixi Lithos

2
@KritixiLithos Richtig.
Orlp

3
Egal, ich habe gerade erkannt, dass der Unterschied wichtig ist, wenn numeine Zweierpotenz vorliegt.
Brian J

11
Dies ist eine triviale Herausforderung mit vielen trivialen Lösungen. Es gibt jedoch auch einige nicht triviale Lösungen. An die Wähler: Bitte lesen Sie den ersten Satz dieses Meta- Posts, bevor Sie die eingebauten Funktionen aufrufen. (Demütig aus diesem Kommentar entnommen )
Kritixi Lithos

Antworten:



35

JavaScript (ES6), 18 Byte

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>


Dies ist eine der wenigen nicht trivialen Lösungen. Schöne Taktik!
Kritixi Lithos

1
Sollte es zu n>>>1unterstützen sein n > 0x7FFFFFFF?
Arnauld

@Arnauld Hmm, wusste nicht, dass es so hoch >>ausgefallen ist n. Vielen Dank.
ETHproductions

Schön, mein erster Versuch warf=(a,b=1)=>a>1?f(a>>1,++b):b
Bassdrop Cumberwubwubwub

28

x86-Assembly, 4 Byte

Unter der Annahme konstant in EBX:

bsr eax,ebx
inc eax

EAX enthält die Anzahl der für Constant erforderlichen Bits.

Bytes: ☼¢├@

Hexadezimal: ['0xf', '0xbd', '0xc3', '0x40']


2
Könnten Sie bitte einen Hexdump des tatsächlich kompilierten 8-Byte-x86-Assembly-Codes einfügen?
Loovjo

Tat so. Und danke, weil mir klar wurde, dass ich einen Fehler gemacht habe. Ich habe ein "inc eax" hinzugefügt, um den Regeln zu entsprechen. Ich habe ein Byte verloren. :(
z0rbergs

Oh wow, du hast meinen Beitrag auf die richtige Formatierung umgestellt. Vielen Dank für die Korrektur!
z0rbergs

2
Übrigens können Assembly-Übermittlungen davon ausgehen, dass die Eingabe bereits in einem bestimmten Register gespeichert ist. Ich denke, Sie könnten auf diese Weise einige Bytes sparen.
Loovjo

1
Ist es üblich, Assembly-Übermittlungen als die Anzahl der Bytes des kompilierten Maschinencodes anstelle des Assemblersprachen-Quellcodes zu zählen?
smls

18

Python , 14 Bytes

int.bit_length

Probieren Sie es online!


Es funktioniert auch in Python 2.
Gewölbe

1
Das tut es in der Tat. Das Int von Forgot Python 2 war 64 Bit breit und nicht 32 Bit.
Dennis

Python 3 bit_lengthist bit_length().
28.

2
@dfernan Dies ist kein Funktionsaufruf. Es ist eine Funktion. Wenn n ist ein int , int.bit_length(n)und n.bit_length()genau das gleiche tun.
Dennis

2
@dfernan int.bit_length(n)ist ein Funktionsaufruf , und damit ein Ausschnitt, der die Eingabe annimmt wird in einer Variablen gespeichert. Dies ist nach unseren Regeln nicht zulässig, daher macht das Anhängen (n)diese Antwort ungültig. Allerdings int.bit_lengthwertet auf eine Funktion und kann in einer Variablen für die spätere Verwendung gespeichert werden. Dies ist standardmäßig erlaubt.
Dennis

15

Labyrinth , 13 12 Bytes

 ?
_:
2/#(!@

Probieren Sie es online!

Erläuterung

Das Programm teilt die Eingabe einfach wiederholt durch 2, bis sie Null ist. Die Anzahl der Schritte wird nachverfolgt, indem der Wert bei jedem Schritt dupliziert wird. Sobald es auf Null reduziert ist, drucken wir die Stapeltiefe (minus 1).

Das Programm startet bei dem, ?der die Eingabe liest. Die Hauptschleife ist dann der darunter liegende 2x2-Block gegen den Uhrzeigersinn:

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

Sobald der Wert nach einer vollständigen Iteration Null ist, wird das lineare Bit am Ende ausgeführt:

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

5
Diese Lösung ist vollständig - sie benötigt Eingaben und liefert die Antwort und verwendet keine vorhandene Funktion für diesen speziellen Zweck - sie berechnet die Antwort manuell. Für mich ist dies mehr im Geiste des Spiels als die meisten anderen Antworten.
Johan

15

C 31 Bytes

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

... Dann habe ich über Rekursion nachgedacht. Von dunkel zu offensichtlich und mit einem Viertel der Länge abgefallen.

Sehen Sie es live auf Coliru


C 43 Bytes

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

Das Aufrufen fmit einem vorzeichenlosen Wert (zB f(42u)) "gibt" seine Bitlänge zurück. Funktioniert sogar für 0u!

Ungolfed und erklärt: (Backslashes weggelassen)

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
    })

Sehen Sie es live auf Coliru


OP garantiert n> = 1, n?...:0ist also nicht notwendig.
Mad Physicist

1
@ MadPhysicist gut, ich muss die Rekursion irgendwo stoppen, nicht
Quentin

OIC. Ich habe nicht genau gelesen, fühle mich jetzt wie ein Idiot. Ordentliche Antwort so oder so.
Mad Physicist

@ MadPhysicist keine Sorgen, vielen Dank :)
Quentin

Für die nicht-rekursive Lösung, die Ausdrücke von gcc-Anweisungen voraussetzt, waren Sie wahrscheinlich auch geneigt, diesen #define f(n) ({64-__builtin_clzl(n);})Ansatz zu verwenden .
Moreaki

14

Mathematica, 9 Bytes

BitLength

Alternative:

Floor@Log2@#+1&
#~IntegerLength~2&

14

Perl 6 , 7 Bytes

*.msb+1

Versuch es

Erläuterung:

* macht es zu einem WhateverCode-Lambda und gibt an, wo die Eingabe erfolgen soll

.msb on an Int liefert den Index des höchstwertigen Bits (0-basiert)

+1wird mit dem Lambda kombiniert und addiert eins zum späteren Ergebnis des Aufrufs .msb.



12

Retina , 56 37 Bytes

Diese Lösung funktioniert mit allen erforderlichen Eingabewerten.

Das größte Problem, mit dem Retina bei dieser Herausforderung konfrontiert ist, ist die Tatsache, dass die Zeichenfolgen eine maximale Länge von 2 ^ 30 Zeichen haben. Daher funktioniert die übliche Art des Umgangs mit Zahlen (unäre Darstellung) nicht mit Werten über 2 ^ 30.

Um dieses Problem zu lösen, habe ich einen anderen Ansatz gewählt, bei dem eine Art Dezimaldarstellung von Zahlen beibehalten wurde , bei der jedoch jede Ziffer unär geschrieben ist (ich bezeichne diese Darstellung als Digitunary ). Zum Beispiel würde die Nummer 341wie 111#1111#1#im Digitunary geschrieben werden. Mit dieser Darstellung können wir jetzt mit Zahlen bis zu 2^30/10Ziffern (~ 100 Millionen Ziffern) arbeiten. Es ist weniger praktisch als Standard für beliebige Arithmetik, aber mit ein wenig Aufwand können wir jede Art von Operation ausführen.

HINWEIS: Digitunary könnte theoretisch jede andere Basis verwenden (z. B. 110wäre Binär 1#1##in Base 2 Digitunary), aber da Retina über integrierte Funktionen zum Konvertieren zwischen Dezimal und Unär verfügt und keine direkte Möglichkeit besteht, mit anderen Basen umzugehen, ist Decimal wahrscheinlich die am besten handhabbare Basis.

Der Algorithmus, den ich verwendet habe, macht aufeinanderfolgende ganzzahlige Divisionen durch zwei, bis wir Null erreichen. Die Anzahl der Divisionen, die wir gemacht haben, ist die Anzahl der Bits, die zur Darstellung dieser Anzahl benötigt werden.

Also, wie teilen wir digital durch zwei? Hier ist das Retina-Snippet, das das macht:

(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

Dieser Ersatz reicht aus, um eine digitale Zahl durch 2 zu teilen. Wenn die ursprüngliche Zahl ungerade war, müssen wir nur mögliche .5s vom Ende entfernen.

Also, hier ist der vollständige Code, wir teilen ihn durch zwei, bis die Zahl noch Ziffern enthält, und setzen nbei jeder Iteration ein Literal vor die Zeichenfolge: Die Zahl nam Ende ist das Ergebnis.

.                  |
$*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

Probieren Sie es online!


Aktualisierte Lösung, 37 Bytes

Großes Refactoring mit vielen guten Ideen, die rund ein Drittel der Länge ausmachten, alles dank Martin Ender!

Die Hauptidee ist, _als unäres Symbol zu verwenden: Auf diese Weise können wir reguläre Ziffern in unserer Zeichenfolge verwenden, solange wir sie _bei Bedarf wieder in s konvertieren. Auf diese Weise können wir beim Teilen und beim Einfügen mehrerer Bytes viele Bytes einsparen Ziffern.

Hier ist der Code:

<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

Probieren Sie es online!


1
Ich habe eine ähnliche numerische Form verwendet (nannte sie aber Unary-Coded Decimal ), was für die Arithmetik mit Sed ziemlich praktisch ist.
Toby Speight

11

Ruby, 19 16 Bytes

->n{"%b"%n=~/$/}

Vielen Dank an Jordan, dass er 3 Bytes abgespielt hat


Sie können ein Byte speichern mit %: ->n{("%b"%n).size}.
Jordanien

3
Warten Sie, das ist kürzer: ->n{"%b"%n=~/$/}.
Jordanien

10

Jolf, 2 Bytes

lB

Einfach in Binär umwandeln und dann die Länge ermitteln.



10

JavaScript ES6, 19 Byte

a=>32-Math.clz32(a)

Math.clz32Gibt die Anzahl der führenden Null-Bits in der 32-Bit-Binärdarstellung einer Zahl zurück. Um die Anzahl der benötigten Bits zu erhalten, müssen wir diese Zahl von 32 abziehen

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
Die Alternative a=>1+Math.log2(a)|0ist auch 19 Bytes.
Neil

5
@ Neil 1+...|0schreit minus Tilde ! a=>-~Math.log2(a)is 18
edc65

@ edc65 Ich zähle 17 ... aber ja, ich war mir sicher, dass ich etwas verpasst habe, danke, dass du darauf hingewiesen hast.
Neil

@Neil Fühlen Sie sich frei, es als separate Antwort zu posten. Es verwendet eine andere Methode als meine Antwort, daher würde es sich unfair anfühlen, Ihre für eine reduzierte
Byteanzahl

10

Bash / Unix-Tools, 16 Byte

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

Speichern Sie dies in einem Skript und übergeben Sie die Eingabe als Argument. Die Anzahl der Bits, die für die Darstellung dieser Zahl in Binärform erforderlich sind, wird gedruckt.

Hier ist eine Erklärung:

dc ist ein stapelbasierter Rechner. Seine Eingabe, die in Token zerlegt wird, lautet:

2 - Schieben Sie 2 auf den Stapel.

o - Entferne einen Wert vom Stack (das ist 2) und mache ihn zur Ausgabebasis (die Ausgabe ist jetzt binär).

Der Wert des Arguments an das Bash-Programm ($ 1) - Verschieben Sie dieses Argument auf den Stapel.

n - Entferne einen Wert vom Stack (das ist die Eingabe-Nummer) und drucke ihn (binär, weil das die Ausgabe-Basis ist) ohne nachfolgende Newline.

Der Befehl dc gibt die Zahl also binär aus.

Die Ausgabe von dc wird mit der Option -c an den Befehl wc weitergeleitet, der die Anzahl der Zeichen in seiner Eingabe ausgibt.

Das Endergebnis besteht darin, die Anzahl der Stellen in der Binärdarstellung des Arguments auszudrucken.


Gute Wahl der Sprache, aber es wäre noch cooler, wenn Sie eine Erklärung hinzufügen.
NH.

@NH Danke. Ich habe eine Erklärung hinzugefügt.
Mitchell Spector

9

Google Sheets, 15 Bytes

Übernimmt die Eingabe von der Zelle A1und gibt sie an die Zelle aus, die die Formel enthält

=Len(Dec2Bin(A1

oder

=Int(1+Log(A1,2

oder

=Int(Log(2*A1,2

Excel, 17 Bytes

Wie oben, jedoch für MS Excel formatiert

=Len(Dec2Bin(A1))

oder

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

oder

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

8

Pyth, 3 Bytes

l.B

Test-Suite hier verfügbar.

Erläuterung

l.BQ    Q is implicitly appended
   Q    eval(input)
 .B     convert Q to binary string
l       len(.B(Q))

Alternativ: hsloder .El, in dem ldie Stammbasis 2 berechnet und / hsoder die .EDecke berechnet wird.
RK.


8

C #, 63 45 31 Bytes

Dank Loovjo und TuukkaX wurden 18 Byte gespeichert

14 Bytes gespart, dank Grax

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

Es wird verwendet, dass eine Dezimalzahl n ⌊log2 (n) ⌋ + 1 Bits hat, was auf dieser Seite beschrieben wird:

Anzahl der Bits in einer bestimmten Dezimalzahl

Eine positive ganze Zahl n hat b Bits, wenn 2 ^ (b-1) ≤ n ≤ 2 ^ b - 1 ist. Zum Beispiel:

  • 29 hat 5 Bits, weil 16 ≤ 29 ≤ 31 oder 2 ^ 4 ≤ 29 ≤ 2 ^ 5 - 1
  • 123 hat 7 Bits, weil 64 ≤ 123 ≤ 127 oder 2 ^ 6 ≤ 123 ≤ 2 ^ 7 - 1
  • 967 hat 10 Bits, weil 512 ≤ 967 ≤ 1023 oder 2 ^ 9 ≤ 967 ≤ 2 ^ 10 - 1

Bei größeren Zahlen können Sie eine Tabelle mit Potenzen von zwei konsultieren, um die aufeinander folgenden Potenzen zu ermitteln, die Ihre Nummer enthalten.

Um zu sehen, warum dies funktioniert, denken Sie beispielsweise an die binären Darstellungen der ganzen Zahlen 2 ^ 4 bis 2 ^ 5 - 1. Es sind 10000 bis 11111, alle möglichen 5-Bit-Werte.

Logarithmen verwenden

Die obige Methode kann anders ausgedrückt werden: Die Anzahl der Bits ist der Exponent der kleinsten Zweierpotenz, die größer ist als Ihre Zahl. Sie können dies mathematisch wie folgt angeben:

bspec = ⌊log2 (n) ⌋ + 1

Diese Formel besteht aus drei Teilen:

  • log2 (n) bedeutet den Logarithmus in der Basis 2 von n, der der Exponent ist, auf den 2 angehoben wird, um n zu erhalten. Zum Beispiel log2 (123) ≈ 6.9425145. Das Vorhandensein eines Bruchteils bedeutet, dass n zwischen Zweierpotenzen liegt.

  • ⌊X⌋ ist der Boden von x, der der ganzzahlige Teil von x ist. Beispiel: ,6.9425145⌋ = 6. Sie können sich ⌊log2 (n) ⌋ als Exponenten der höchsten Zweierpotenz in der Binärdarstellung von n vorstellen.

  • +1 bringt den Exponenten zur nächsthöheren Zweierpotenz. Sie können sich diesen Schritt so vorstellen, dass Sie die 2 ^ 0-Stelle Ihrer Binärzahl berücksichtigen, die dann die Gesamtzahl der Bits angibt. In unserem Beispiel ist das 6 + 1 = 7. Sie könnten versucht sein, die Deckenfunktion - ⌈x⌈, die die kleinste Ganzzahl größer oder gleich x ist - zu verwenden, um die Anzahl der Bits als solche zu berechnen:

bspec = ⌈log2 (n) ⌉

Dies schlägt jedoch fehl, wenn n eine Zweierpotenz ist.


Sie haben dort einen zusätzlichen Platz ...)+ 1)...-> ...)+1.... Ich denke auch, dass Sie den Wert direkt zurückgeben können, anstatt ihn zu drucken.
Loovjo

Sie können es auf 31 setzen, indem b=>1+(int)System.Math.Log(b,2); Sie Folgendes ausführen: Die int-Konvertierung liefert die gleiche Ausgabe wie Math.Floor, und Sie benötigen die using-Anweisung nicht, wenn Sie nur einmal auf System verweisen.
Grax32

6

C #, 32 Bytes

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

Konvertiert den Parameter in eine Binärzeichenfolge und gibt die Länge der Zeichenfolge zurück.


4

Haskell, 20 Bytes

succ.floor.logBase 2

Verfasst eine Funktion, die die Logarithmusbasis 2, Fußböden und Addition 1 annimmt.


4

Befunge-93 , 23 21 Bytes

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

Befunge ist eine auf 2D-Rastern basierende Sprache (obwohl ich nur eine Zeile verwende).

&                      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

Probieren Sie es online!


@ JamesHolderness Danke, ich dachte, es könnte gekürzt werden, da es so viele Hash / Leerzeichen hat, aber ich konnte es nicht ganz verstehen.
JayDepp





3

QBIC , 18 Bytes

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

Das ist unglaublich, Mike! Aber wie geht das?

:        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

Java 8, 34 27 Bytes

Für einmal hat Java einige nützliche eingebaute Funktionen! Jetzt brauchen wir nur noch ein paar kürzere Namen ...

x->x.toString(x,2).length()

Probieren Sie es online!

Natürlich können Sie dies auch ohne integrierte Funktionen tun ( siehe Schneemanns Antwort ), jedoch für eine höhere Byteanzahl .


3

Oktave, 19 Bytes

@(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 hat zwei Funktionen zum Konvertieren von Dezimalzahlen in Binärzahlen.

dec2binkonvertiert eine Zahl in eine Zeichenkette 1und 0(ASCII-Werte 48und 49). Die Länge der Zeichenfolge entspricht der erforderlichen Anzahl von Bits, sofern nicht anders angegeben. Da die Zeichen 1und 0Nicht-Null sind, können wir verwenden , um nnzdie Anzahl der Elemente wie folgt zu finden: @(x)nnz(dec2bin(x)). Das sind 19 Bytes, also ist es mit Luis Mendos anderer Octave-Antwort verknüpft .

Können wir es besser machen de2bi?

de2biist eine Funktion, die die Binärzahlen als Vektor mit den Zahlen 1und 0als Ganzzahlen und nicht als Zeichen zurückgibt . de2biist offensichtlich zwei Bytes kürzer als dec2bin, aber wir können nicht mehr verwenden nnz. Wir können es verwenden, nnzwenn wir entweder 1zu allen Elementen hinzufügen oder es zu einem logischen Vektor mit nur trueWerten machen. @(x)nnz(de2bi(x)+1)und @(x)nnz(de2bi(x)<2)sind beide 19 Bytes. Wenn Sie verwenden numel, erhalten Sie auch 19 Byte @(x)numel(de2bi(x)).

rowsist ein Byte kürzer als numel, gibt aber de2bieinen horizontalen Vektor zurück, muss also transponiert werden. @(x)rows(de2bi(x)')Zufällig sind es auch 19 Bytes.



2

Retina ,  44  23 Bytes

Benötigt zu viel Speicher für große Eingabewerte. Wandelt in Unary um und dividiert dann wiederholt durch 2, wobei gezählt wird, wie oft, bis Null erreicht wird. Die Anzahl der Bytes setzt die Kodierung nach ISO 8859-1 voraus.

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

Probieren Sie es online aus


1
Ich bin mir nicht sicher, ob das gültig ist. Dies ist kein Fall von "es erfordert mehr Speicher als Sie wahrscheinlich haben", sondern "es erfordert mehr Speicher als Retina selbst verarbeiten kann". Insbesondere wird die anfängliche Konvertierung in Unary für Eingaben der Ordnung 2 ^ 30 und höher aufgrund von Einschränkungen in der Implementierung von Retina fehlschlagen.
Martin Ender

Wenn es gültig ist, könnte es jedoch erheblich
Martin Ender
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.