Dans combien de bits est-ce que je rentre


52

Pour tout entier positif sur 32 bits ( 1 ≤ n ≤ 0xFFFFFFFF), indiquez le nombre de bits nécessaires pour représenter cet entier.

Cas de test

| 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

Donc f(16), imprimer ou retourner5

C'est du . Le code le plus court en octets gagne


2
C'est le plafond du logarithme en base 2.
Orlp

23
@ orlp C'est en faitfloor(log2(num))+1
Kritixi Lithos

2
@KritixiLithos Right.
Orlp

3
Peu importe, je viens de me rendre compte que le distinct est important quand numest une puissance de deux.
Brian J

11
C'est un défi trivial avec beaucoup de solutions triviales. Il existe toutefois des solutions non triviales. Aux électeurs: Veuillez lire la première phrase de cette publication avant de voter pour les fonctions intégrées. (humblement tiré de ce commentaire )
Kritixi Lithos

Réponses:



35

JavaScript (ES6), 18 octets

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>


C'est l'une des rares solutions non triviales ici. Belle tactique!
Commentaires

1
Cela devrait-il être n>>>1supporté n > 0x7FFFFFFF?
Arnauld

@Arnauld Hmm, ne savait pas a >>échoué sur ncette haute. Merci.
ETHproductions

f=(a,b=1)=>a>1?f(a>>1,++b):b
Bien

28

Assemblage x86, 4 octets

En supposant Constant dans EBX:

bsr eax,ebx
inc eax

EAX contient le nombre de bits nécessaires pour Constant.

Octets: ☼¢├@

Hexadécimal: ['0xf', '0xbd', '0xc3', '0x40']


2
Pourriez-vous s'il vous plaît inclure un vidage hexadécimal du code d'assemblage x86 compilé sur 8 octets?
Loovjo

L'a fait. Et merci, car j'ai réalisé que j'avais commis une erreur. J'ai ajouté un "inc eax" pour répondre aux règles. J'ai perdu un octet. :(
le

Oh wow tu as changé mon post en formatage correct. Merci de l'avoir corrigé!
Le

2
En passant, les soumissions de l'Assemblée peuvent supposer que l'entrée est déjà stockée dans un registre spécifique . Je pense donc que vous pourriez supprimer quelques octets de cette façon.
Loovjo

1
Est-il habituel de compter les soumissions d'assembly comme le nombre d'octets du code machine compilé plutôt que le code source du langage assembleur?
smls

18

Python , 14 octets

int.bit_length

Essayez-le en ligne!


Cela fonctionne également dans Python 2.
vaultah

1
C'est vrai. Le format int de Forgot Python 2 était large de 64 bits et non de 32 bits.
Dennis

Python 3 bit_lengthest bit_length().
dfernan

2
@dfernan Ceci n'est pas un appel de fonction; c'est une fonction. Si n est un entier , int.bit_length(n)et n.bit_length()faire exactement la même chose.
Dennis

2
@dfernan int.bit_length(n)est un appel de fonction et constitue donc un fragment qui suppose que l'entrée est stockée dans une variable. Ceci est pas permis par nos règles, donc annexant (n)rendrait invalide cette réponse. Cependant, int.bit_lengthévalue une fonction et peut être enregistré dans une variable pour une utilisation ultérieure. Ceci est autorisé par défaut.
Dennis

15

Labyrinth , 13 à 12 octets

 ?
_:
2/#(!@

Essayez-le en ligne!

Explication

Le programme divise simplement l’entrée par 2 jusqu’à zéro. Le nombre d'étapes est maintenu en dupliquant la valeur à chaque étape. Une fois réduit à zéro, nous imprimons la profondeur de la pile (moins 1).

Le programme commence par le ?qui lit l'entrée. La boucle principale est alors le bloc 2x2 ci-dessous, en sens antihoraire:

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

Une fois que la valeur est zéro après une itération complète, le bit linéaire à la fin est exécuté:

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

5
Cette solution est complète - prend les entrées et fournit la réponse, et n’utilise aucune fonction existante à cette fin - elle calcule la réponse manuellement. Pour moi, cela correspond plus à l'esprit du jeu qu'à la plupart des autres réponses.
Johan

15

C, 31 octets

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

... Puis j'ai pensé à la récursivité. D'obscur à évident, et avec un quart de la longueur déposée.

Voir en direct sur Coliru


C, 43 octets

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

Appeler favec une valeur non signée (par exemple f(42u)) "retournera" sa longueur en bits. Même travaille pour 0u!

Non golfé et expliqué: (barres obliques inverses omises)

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

Voir en direct sur Coliru


OP garantit n> = 1, donc ce n?...:0n’est pas nécessaire.
Mad Physicist

1
@MadPhysicist et bien je dois arrêter la récursion quelque part, n'est-ce pas;)
Quentin

OCI. Je n'ai pas lu attentivement, je me sens comme un imbécile maintenant. Réponse soignée de toute façon.
Mad Physicist

@MadPhysicist pas de soucis, merci beaucoup :)
Quentin

Pour la solution non récursive supposant des expressions gcc, j’imagine que vous auriez peut-être eu tendance à utiliser également cette #define f(n) ({64-__builtin_clzl(n);})approche.
Moreaki

14

Mathematica, 9 octets

BitLength

Alternativement:

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

14

Perl 6 , 7 octets

*.msb+1

L'essayer

Explication:

* le fait devenir un lambda WhateverCode, et indique où mettre l'entrée

.msb sur un Int retourne l'index du bit le plus significatif (basé sur 0)

+1est combiné dans le lambda, et ajoute un au résultat final de l'appel .msb.



12

Retina , 56 37 bytes

Cette solution fonctionne avec toutes les valeurs d'entrée requises.

Le problème le plus important auquel Retina est confrontée dans ce défi est le fait que ses chaînes ont une longueur maximale de 2 ^ 30 caractères. Par conséquent, la manière habituelle de traiter les nombres (représentation unaire) ne fonctionne pas avec des valeurs supérieures à 2 ^ 30.

Afin de résoudre ce problème, j’ai adopté une approche différente en conservant une sorte de représentation décimale des nombres, mais où chaque chiffre est écrit en unaire (je vais appeler cette représentation numérique ). Par exemple, le nombre 341serait écrit comme 111#1111#1#dans digitunary. Avec cette représentation, nous pouvons maintenant travailler avec des nombres allant jusqu'à un 2^30/10chiffre (environ cent millions de chiffres). C'est moins pratique que le unaire classique pour l'arithmétique arbitraire, mais avec un peu d'effort, nous pourrions faire n'importe quel type d'opération.

REMARQUE: digitunary pourrait théoriquement utiliser n'importe quelle autre base (par exemple binaire 110serait 1#1##en base 2 digitunary), mais puisque Retina a été conçu pour effectuer la conversion entre décimales et unaires et qu'il n'existe aucun moyen direct de traiter d'autres bases, la décimale est probablement la base la plus facile à gérer.

L'algorithme que j'ai utilisé consiste à faire des divisions entières successives par deux jusqu'à atteindre zéro, le nombre de divisions que nous avons fait est le nombre de bits nécessaires pour représenter ce nombre.

Alors, comment divisons-nous par deux en numérique? Voici l'extrait de la rétine qui le fait:

(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

Ce remplacement est suffisant pour diviser un nombre numérique par 2, il suffit d’enlever les .5 possibles à la fin si le nombre initial était impair.

Donc, voici le code complet, nous continuons à diviser par deux jusqu'à ce qu'il y ait encore des chiffres dans le nombre, et mettons un littéral ndevant la chaîne à chaque itération: le nombre nà la fin est le résultat.

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

Essayez-le en ligne!


Solution mise à jour, 37 octets

Grand refactoring avec beaucoup de bonnes idées qui ont golfé environ un tiers de la longueur, tout cela grâce à Martin Ender!

L’idée principale est d’utiliser _comme symbole unaire: de cette manière, nous pouvons utiliser des chiffres normaux dans notre chaîne, à condition de les reconvertir en _s lorsque cela est nécessaire: cela nous permet d’économiser de nombreux octets lors de la division et de l’insertion de multiples. chiffres.

Voici le 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

Essayez-le en ligne!


1
J'ai utilisé une forme numérique similaire (mais appelée la décimale codée unaire ), ce qui est très pratique pour l'arithmétique avec Sed.
Toby Speight

11

Ruby, 19 16 octets

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

Merci Jordan pour le golf 3 octets


Vous pouvez enregistrer un octet avec %: ->n{("%b"%n).size}.
Jordanie

3
Attendez, cela est plus court: ->n{"%b"%n=~/$/}.
Jordanie

10

Jolf, 2 octets

lB

Il suffit de convertir en binaire, puis de trouver la longueur.



10

JavaScript ES6, 19 octets

a=>32-Math.clz32(a)

Math.clz32renvoie le nombre de bits zéro dans la représentation binaire 32 bits d'un nombre. Donc, pour obtenir le nombre de bits nécessaires, il suffit de soustraire ce nombre de 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
L'alternative a=>1+Math.log2(a)|0est également 19 octets.
Neil

5
@ Neil 1+...|0crie moins tilde ! a=>-~Math.log2(a)est 18
edc65

@ edc65 Je compte 17 ... mais oui, j'étais sûr qu'il me manquait quelque chose, merci de l'avoir signalé.
Neil

@ Neil Ne hésitez pas à le poster comme une réponse distincte. Il utilise une méthode différente de ma réponse, il serait donc injuste d'utiliser le vôtre pour réduire le nombre d'octets
Bassdrop Cumberwubwubwub

10

Outils bash / Unix, 16 octets

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

Enregistrez ceci dans un script et transmettez l'entrée sous forme d'argument. Le nombre de bits requis pour représenter ce nombre en binaire sera imprimé.

Voici une explication:

dc est une calculatrice basée sur des piles. Son entrée, analysée en jetons, est la suivante:

2 - Poussez 2 sur la pile.

o - Extrait une valeur de la pile (qui est 2) et en fait la base de sortie (la sortie est maintenant en binaire).

La valeur de l'argument du programme bash ($ 1) - Envoie cet argument dans la pile.

n - Extrait une valeur de la pile (qui est le numéro d'entrée) et l'affiche (en binaire, car c'est la base de sortie) sans fin de nouvelle ligne.

Donc, la commande dc affiche le nombre en binaire.

La sortie de dc est transmise à la commande wc avec l’option -c, qui affiche le nombre de caractères de son entrée.

Le résultat final consiste à imprimer le nombre de chiffres dans la représentation binaire de l'argument.


Bon choix de langue, mais ce serait encore plus cool si vous incluiez une explication.
NH.

@NH Merci. J'ai ajouté une explication.
Mitchell Spector

9

Google Sheets, 15 octets

Prend les entrées de la cellule A1et les sorties dans la cellule qui contient la formule

=Len(Dec2Bin(A1

ou

=Int(1+Log(A1,2

ou

=Int(Log(2*A1,2

Excel, 17 octets

Comme ci-dessus mais formaté pour MS Excel

=Len(Dec2Bin(A1))

ou

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

ou

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



8

C #, 63 45 31 octets

Sauvegardé 18 octets, grâce à Loovjo et TuukkaX

14 octets sauvés, merci à Grax

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

Il utilise, qu'un nombre décimal n a ⌊log2 (n) ⌋ + 1 bits, ce qui est décrit sur cette page:

Nombre de bits dans un entier décimal spécifique

Un entier positif n a b bits lorsque 2 ^ (b-1) ≤ n ≤ 2 ^ b - 1. Par exemple:

  • 29 a 5 bits parce que 16 ≤ 29 ≤ 31 ou 2 ^ 4 ≤ 29 ≤ 2 ^ 5 - 1
  • 123 a 7 bits parce que 64 ≤ 123 ≤ 127 ou 2 ^ 6 ≤ 123 ≤ 2 ^ 7 - 1
  • 967 a 10 bits parce que 512 ≤ 967 ≤ 1023 ou 2 ^ 9 ≤ 967 ≤ 2 ^ 10 - 1

Pour des nombres plus importants, vous pouvez consulter une table des pouvoirs de deux pour trouver les pouvoirs consécutifs contenant votre numéro.

Pour voir pourquoi cela fonctionne, pensez aux représentations binaires des entiers 2 ^ 4 à 2 ^ 5 - 1, par exemple. Ils sont compris entre 10000 et 11111, toutes les valeurs possibles sur 5 bits.

Utilisation de logarithmes

La méthode ci-dessus peut être énoncée d'une autre manière: le nombre de bits est l'exposant de la plus petite puissance de deux supérieure à votre nombre. Vous pouvez indiquer cela mathématiquement:

bspec = ⌊log2 (n) + 1

Cette formule comporte trois parties:

  • log2 (n) signifie le logarithme en base 2 de n, qui est l'exposant auquel 2 est élevé pour obtenir n. Par exemple, log2 (123) ≈ 6.9425145. La présence d'une partie fractionnaire signifie que n est compris entre deux puissances.

  • ⌊X⌋ est le plancher de x, qui est la partie entière de x. Par exemple, .96.9425145⌋ = 6. Vous pouvez considérer ⌊log2 (n) ⌋ comme l'exposant de la plus grande puissance de deux dans la représentation binaire de n.

  • +1 prend l'exposant à la puissance immédiatement supérieure de deux. Vous pouvez considérer cette étape comme une comptabilisation de la 2 ^ 0e place de votre nombre binaire, qui vous donne ensuite son nombre total de bits. Pour notre exemple, 6 + 1 = 7. Vous pourriez être tenté d'utiliser la fonction de plafond - x⌉, qui est le plus petit entier supérieur ou égal à x - pour calculer le nombre de bits en tant que tel:

bspec = ⌈log2 (n) ⌉

Cependant, cela échoue lorsque n est une puissance de deux.


Vous avez un espace supplémentaire là ...)+ 1)...-> ...)+1.... De plus, je pense que vous pouvez renvoyer la valeur directement au lieu de l’imprimer.
Loovjo

Vous pouvez b=>1+(int)System.Math.Log(b,2); le ramener à 31 en faisant cela. La conversion int fournit le même résultat que Math.Floor et vous n'avez pas besoin de l'instruction using si vous ne faites référence à System qu'une seule fois.
Grax32

6

C #, 32 octets

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

Convertit le paramètre en chaîne binaire et renvoie la longueur de la chaîne.


4

Haskell, 20 octets

succ.floor.logBase 2

Compose une fonction qui prend en logarithme 2, étages et ajoute 1.


4

Befunge-93 , 23 à 21 octets

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

Befunge est un langage basé sur une grille 2D (bien que je n’utilise qu’une seule ligne).

&                      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

Essayez-le en ligne!


@ JamesHolderness Merci, j'ai pensé qu'il pourrait être raccourci car il y avait tellement de hash / espaces, mais je ne pouvais pas tout à fait l'obtenir.
JayDepp





3

QBIC , 18 octets

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

C'est incroyable Mike! Mais comment ça fonctionne?

:        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 octets

Pour une fois, Java a quelques fonctions utiles! Maintenant, nous avons juste besoin de noms plus courts ...

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

Essayez-le en ligne!

Bien sûr, vous pouvez le faire sans fonctions intégrées ( voir la réponse de Snowman ), mais pour un nombre d'octets plus élevé.


3

Octave, 19 octets

@(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 a deux fonctions pour convertir les nombres décimaux en nombres binaires.

dec2binconvertit un nombre en une chaîne de caractères 1et 0(valeurs ASCII 48et 49). La longueur de la chaîne sera égale au nombre de bits nécessaire, sauf indication contraire. Étant donné que les caractères 1et ne 0sont pas nuls, nous pouvons utiliser nnzpour trouver le nombre d'éléments comme celui - ci: @(x)nnz(dec2bin(x)). C'est 19 octets, donc c'est à égalité avec l'autre réponse Octave de Luis Mendo .

Pouvons-nous mieux utiliser de2bi?

de2biest une fonction qui renvoie les nombres binaires sous forme de vecteur avec les nombres 1et 0sous forme d’entiers, pas de caractères. de2biest évidemment deux octets plus court que dec2bin, mais nous ne pouvons plus utiliser nnz. Nous pouvons utiliser nnzsi nous ajoutons 1tous les éléments ou si nous en faisons un vecteur logique avec uniquement des truevaleurs. @(x)nnz(de2bi(x)+1)et @(x)nnz(de2bi(x)<2)sont tous deux 19 octets. En utilisantnumel également nous donner 19 octets, @(x)numel(de2bi(x)).

rowsest un octet plus court que numel, mais de2birenvoie un vecteur horizontal, il doit donc être transposé. @(x)rows(de2bi(x)')Il se trouve qu’il s’agit également de 19 octets.



2

Retina ,  44  23 octets

Nécessite trop de mémoire pour pouvoir exécuter des valeurs d’entrée importantes. Convertit en unaire, puis divise à plusieurs reprises par 2, en comptant combien de fois jusqu'à atteindre zéro. Le nombre d'octets suppose un codage ISO 8859-1.

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

Essayez-le en ligne


1
Je ne suis pas sûr que cela soit valide. Ce n'est pas un cas de "cela nécessite plus de mémoire que vous n'en aurez probablement", mais "cela nécessite plus de mémoire que Retina ne peut en gérer". En particulier, la conversion initiale en unaire échouera pour les entrées d'ordre 2 à 30 et plus, en raison de limitations dans la mise en œuvre de Retina.
Martin Ender

Si elle est valide, il pourrait être raccourci si beaucoup: tio.run/nexus/retina#@6@nxaWixaWdEKdhqK1paB9jyKViGM@l9/@/saUhAA
Martin Ender
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.