Em quantos bits eu me encaixo


52

Para qualquer número inteiro positivo de 32 bits ( 1 ≤ n ≤ 0xFFFFFFFF), o número de bits necessário para representar esse número inteiro.

Casos de teste

| 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

Então f(16), imprimiria ou retornaria5

Isso é . O menor código em bytes ganha


2
Este é o teto do logaritmo base-2.
orlp

23
@orlp Na verdade é #floor(log2(num))+1
Kritixi Lithos

2
@KritixiLithos Right.
Orlp

3
Deixa pra lá, só percebi que o distinto é importante quando numhá uma potência de dois.
Brian J

11
Este é um desafio trivial com muitas soluções triviais. No entanto, existem algumas soluções não triviais também. Para os eleitores: Leia a primeira frase desta meta postagem antes de votar nas funções internas. (humildemente tomadas a partir deste comentário )
Kritixi Lithos

Respostas:



35

JavaScript (ES6), 18 bytes

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>


Esta é uma das poucas soluções não triviais aqui. Boa tática!
Kritixi Lithos

11
Deveria ser n>>>1para apoiar n > 0x7FFFFFFF?
Arnauld

@ Arnauld Hmm, não sabia que >>falhou nnessa altura. Obrigado.
ETHproductions

Bom, minha primeira tentativa foi #f=(a,b=1)=>a>1?f(a>>1,++b):b
Bassdrop Cumberwubwubwub

28

Montagem x86, 4 bytes

Assumindo constante em EBX:

bsr eax,ebx
inc eax

EAX contém o número de bits necessários para Constant.

Bytes: ☼¢├@

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


2
Você poderia incluir um hexdump do código real do Assembly x86 compilado de 8 bytes?
Loovjo 27/12/16

Fiz assim. E obrigado, porque percebi que cometi um erro. Eu adicionei um "inc eax" para atender às regras. Perdi um byte. :(
27/12/16 de z0rberg

Oh uau, você mudou meu post para formatação adequada. Obrigado por corrigi-lo!
z0rberg's dec

2
A propósito, as submissões do Assembly podem assumir que a entrada já está armazenada em um registro específico , então acho que você pode economizar alguns bytes dessa maneira.
Loovjo 27/12/16

11
É habitual contar os envios de assembly como o número de bytes do código de máquina compilado em vez do código-fonte da linguagem de assembly?
SMLS

18

Python , 14 bytes

int.bit_length

Experimente online!


Também funciona em Python 2.
vaultah

11
De fato. Esqueceu que o int do Python 2 tinha 64 bits de largura, não 32 bits.
Dennis

Python 3 bit_lengthé bit_length().
dfernan

2
@ dfernan Esta não é uma chamada de função; é uma função. Se n é um int , int.bit_length(n)e n.bit_length()faça exatamente o mesmo.
Dennis

2
@dfernan int.bit_length(n)é uma chamada de função e, portanto, um trecho que assume que a entrada está armazenada em uma variável. Isso não é permitido por nossas regras, portanto, anexar (n)tornaria esta resposta inválida. No entanto, int.bit_lengthavalia uma função e pode ser salva em uma variável para uso posterior. Isso é permitido por padrão.
Dennis

15

Labirinto , 13 12 bytes

 ?
_:
2/#(!@

Experimente online!

Explicação

O programa simplesmente divide repetidamente a entrada por 2 até que seja zero. O número de etapas é monitorado duplicando o valor em cada etapa. Depois de reduzido a zero, imprimimos a profundidade da pilha (menos 1).

O programa inicia no ?qual lê a entrada. O loop principal é o bloco 2x2 abaixo, no sentido anti-horário:

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

Quando o valor é zero após uma iteração completa, o bit linear no final é executado:

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

5
Esta solução está completa - recebe entrada e fornece a resposta e não utiliza nenhuma função existente para esse fim específico - calcula a resposta manualmente. Para mim, isso está mais no espírito do jogo do que na maioria das outras respostas.
27416 Johan Johan

15

C, 31 bytes

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

... Então pensei em recursão. De obscuro para óbvio, e com um quarto do comprimento caiu.

Veja ao vivo em Coliru


C, 43 bytes

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

Chamar fcom um valor não assinado (por exemplo f(42u)) "retornará" seu tamanho de bit. Até funciona 0u!

Ungolfed e explicado: (barras invertidas omitidas)

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

Veja ao vivo em Coliru


OP garante n> = 1, portanto, n?...:0não é necessário.
Mad Physicist

11
@MadPhysicist bem, eu tenho que parar a algum lugar recursão, não eu;)
Quentin

OIC. Não leu com cuidado, sinto como um idiota agora. Resposta pura de qualquer maneira.
Mad Physicist

@MadPhysicist não se preocupe, muito obrigado :)
Quentin

Para a solução não recursiva assumindo expressões de instrução gcc, eu acho que você também pode ter se inclinado a usar a #define f(n) ({64-__builtin_clzl(n);})abordagem.
Moreaki 01/01

14

Mathematica, 9 bytes

BitLength

Alternativamente:

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

14

Perl 6 , 7 bytes

*.msb+1

Tente

Explicação:

* torna-o um lambda WhateverCode e indica onde colocar a entrada

.msb em um Int retorna o índice do bit mais significativo (baseado em 0)

+1é combinado no lambda e adiciona um ao resultado final da chamada .msb.


13

Macro do pré-processador C (com extensões gcc), 26

#define f 32-__builtin_clz

Usa o built -in-zeros da contagem do GCC .

Chame isso como uma função, por exemplo f(100).

Experimente online .


Oh, uau, pensei em usar um builtin, mas desisti da ideia porque achei que seria muito longo ... Bem jogado.
Quentin

Sorte que o OP especificou n> = 1: D
Matthieu M.

12

Retina , 56 37 bytes

Esta solução funciona com todos os valores de entrada necessários.

O maior problema que Retina enfrenta nesse desafio é o fato de suas seqüências terem um comprimento máximo de 2 ^ 30 caracteres, portanto, a maneira usual de lidar com números (representação unária) não funciona com valores maiores que 2 ^ 30.

Para resolver esse problema, adotei uma abordagem diferente, mantendo uma espécie de representação decimal dos números, mas onde cada dígito é escrito em unário (chamarei essa representação de digitunário ). Por exemplo, o número 341seria escrito como 111#1111#1#num dígito. Com essa representação, agora podemos trabalhar com números de até 2^30/10dígitos (~ cem milhões de dígitos). É menos prático que o padrão unário para aritmética arbitrária, mas com um pouco de esforço, poderíamos realizar qualquer tipo de operação.

OBSERVAÇÃO: em teoria, o digitunary poderia usar qualquer outra base (por exemplo, o binário 110estaria 1#1##na base 2 do digitunary), mas, como o Retina possui builtins para converter entre decimal e unário e nenhuma maneira direta de lidar com outras bases, o decimal é provavelmente a base mais gerenciável.

O algoritmo que usei faz divisões inteiras sucessivas por dois até chegarmos a zero, o número de divisões que criamos é o número de bits necessários para representar esse número.

Então, como é que vamos dividir por dois em dois dígitos? Aqui está o trecho de Retina que faz isso:

(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

Essa substituição é suficiente para dividir um número digitunário por 2; basta remover 0,5s possíveis do final, se o número original for ímpar.

Então, aqui está o código completo, continuamos dividindo por dois até que ainda haja dígitos no número e colocamos um literal nna frente da string a cada iteração: o número de nno final é o resultado.

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

Experimente online!


Solução atualizada, 37 bytes

Grande refatoração com muitas boas idéias que jogaram cerca de um terço do comprimento, tudo graças a Martin Ender!

A idéia principal é usar _como símbolo unário: dessa maneira, podemos usar dígitos regulares em nossa string, desde que os convertamos de volta para _s quando necessário: isso permite salvar muitos bytes na divisão e na inserção de múltiplos dígitos.

Aqui está o código:

<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

Experimente online!


11
Eu usei uma forma numérica semelhante (mas denominada Decimal com código unário ), que é bastante útil para aritmética com o Sed.
Toby Speight

11

Ruby, 19 16 bytes

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

Obrigado Jordan por jogar fora 3 bytes


Você pode salvar um byte com %: ->n{("%b"%n).size}.
Jordan

3
Espere, isso é mais curto: ->n{"%b"%n=~/$/}.
Jordan

10

Jolf, 2 bytes

lB

Basta converter em binário e, em seguida, encontre o comprimento.



10

JavaScript ES6, 19 bytes

a=>32-Math.clz32(a)

Math.clz32retorna o número de zero bits à esquerda na representação binária de 32 bits de um número. Então, para obter a quantidade de bits necessária, tudo o que precisamos fazer é subtrair esse número 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
A alternativa a=>1+Math.log2(a)|0também é 19 bytes.
27516 Neil

5
@ Neil 1+...|0grita menos til ! a=>-~Math.log2(a)é 18
edc65

@ edc65 conto 17 ... mas sim, eu tinha certeza de que estava perdendo alguma coisa, obrigado por apontar.
Neil

@ Neil Sinta-se livre para publicá-lo como uma resposta separada. Ele usa um método diferente do que a minha resposta para que ele iria se sentir injusto para usar o seu para uma contagem de bytes reduzida
Bassdrop Cumberwubwubwub

10

ferramentas bash / Unix, 16 bytes

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

Salve isso em um script e passe a entrada como argumento. O número de bits necessários para representar esse número em binário será impresso.

Aqui está uma explicação:

dc é uma calculadora baseada em pilha. Sua entrada, analisada em tokens, é:

2 - Pressione 2 na pilha.

o - Retire um valor da pilha (que é 2) e torne-o a base de saída (para que a saída agora seja binária).

O valor do argumento para o programa bash ($ 1) - Empurre esse argumento na pilha.

n - Retire um valor da pilha (que é o número de entrada) e imprima-o (em binário, porque essa é a base de saída) sem nova linha final.

Portanto, o comando dc imprime o número em binário.

A saída de dc é canalizada para o comando wc com a opção -c, que imprime o número de caracteres em sua entrada.

O resultado final é imprimir o número de dígitos na representação binária do argumento.


Boa escolha de idioma, mas seria ainda mais interessante se você incluísse uma explicação.
NH.

@ NH Obrigado. Eu adicionei uma explicação.
Mitchell Spector

9

Planilhas Google, 15 bytes

Leva a entrada da célula A1e sai para a célula que contém a fórmula

=Len(Dec2Bin(A1

ou

=Int(1+Log(A1,2

ou

=Int(Log(2*A1,2

Excel, 17 bytes

O mesmo que acima, mas formatado para o MS Excel

=Len(Dec2Bin(A1))

ou

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

ou

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



8

C #, 63 45 31 bytes

Economizou 18 bytes, graças a Loovjo e TuukkaX

Economizou 14 bytes, graças ao Grax

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

Ele usa que um número decimal n tem ⌊log2 (n) ⌋ + 1 bits, descrito nesta página:

Número de bits em um número inteiro decimal específico

Um número inteiro positivo n tem b bits quando 2 ^ (b-1) ≤ n ≤ 2 ^ b - 1. Por exemplo:

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

Para números maiores, você pode consultar uma tabela de potências de dois para encontrar as potências consecutivas que contêm seu número.

Para ver por que isso funciona, pense nas representações binárias dos números inteiros 2 ^ 4 a 2 ^ 5 - 1, por exemplo. São de 10000 a 11111, todos os valores possíveis de 5 bits.

Usando logaritmos

O método acima pode ser dito de outra maneira: o número de bits é o expoente da menor potência de dois maior que o seu número. Você pode declarar isso matematicamente como:

bspec = log2 (n) + 1

Essa fórmula tem três partes:

  • log2 (n) significa o logaritmo na base 2 de n, que é o expoente ao qual 2 é elevado para obter n. Por exemplo, log2 (123) ≈ 6.9425145. A presença de uma parte fracionária significa que n está entre potências de dois.

  • ⌊X⌋ é o piso de x, que é a parte inteira de x. Por exemplo, .96.9425145⌋ = 6. Você pode pensar em 2log2 (n) ⌋ como o expoente da potência mais alta de dois na representação binária de n.

  • +1 leva o expoente para a próxima potência mais alta de dois. Você pode pensar nesta etapa como responsável pelo 2 ° 0 ° lugar do seu número binário, o que lhe dá o número total de bits. Para o nosso exemplo, isso é 6 + 1 = 7. Você pode tentar usar a função de teto - ⌈x⌈, que é o menor número inteiro maior que ou igual a x - para calcular o número de bits da seguinte forma:

bspec = log2 (n)

No entanto, isso falha quando n é uma potência de dois.


Você tem um espaço extra lá ...)+ 1)...-> ...)+1.... Além disso, acho que você pode retornar o valor diretamente em vez de imprimi-lo.
Loovjo

Você pode reduzi-lo para 31 fazendo b=>1+(int)System.Math.Log(b,2); A conversão int fornece a mesma saída que Math.Floor e você não precisa da instrução using se fizer referência apenas ao sistema uma vez.
Grax32

6

C #, 32 bytes

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

Converte o parâmetro em uma string binária e retorna o comprimento da string.


4

Haskell, 20 bytes

succ.floor.logBase 2

Compõe uma função que usa o logaritmo base 2, pisos e adiciona 1.


4

Befunge-93 , 23 21 bytes

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

Befunge é uma linguagem baseada em grade 2D (embora eu esteja usando apenas uma linha).

&                      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

Experimente online!


@JamesHolderness Obrigado, achei que poderia ser reduzido, pois tinha tantos hash / espaços, mas não consegui entender.
JayDepp





3

QBIC , 18 bytes

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

Mike incrível! Mas como isso funciona?

:        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

Pela primeira vez, o Java tem alguns recursos úteis! Agora, só precisamos de nomes mais curtos ...

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

Experimente online!

Obviamente, você pode fazer isso sem os recursos internos ( consulte a resposta do Snowman ), mas para obter uma contagem maior de bytes.


3

Oitava, 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'))

Oitava tem duas funções para converter números decimais em números binários.

dec2binconverte um número em uma sequência de caracteres 1e 0(valores ASCII 48e 49). O comprimento da string será igual ao número necessário de bits, a menos que especificado de outra forma. Uma vez que os caracteres 1e 0são diferentes de zero, podemos usar nnzpara encontrar o número de elementos como este: @(x)nnz(dec2bin(x)). São 19 bytes, por isso está relacionado à outra resposta oitava de Luis Mendo .

Podemos fazer melhor usando de2bi?

de2bié uma função que retorna os números binários como um vetor com os números 1e 0como números inteiros, não caracteres. de2bié obviamente dois bytes menor que dec2bin, mas não podemos mais usar nnz. Nós podemos usar nnzse quer adicionar 1a todos os elementos, ou torna-lo em um vetor lógico com apenas truevalores. @(x)nnz(de2bi(x)+1)e @(x)nnz(de2bi(x)<2)são ambos 19 bytes. Usar numeltambém nos dará 19 bytes @(x)numel(de2bi(x)),.

rowsé um byte menor que numel, mas de2biretorna um vetor horizontal; portanto, ele deve ser transposto. @(x)rows(de2bi(x)')acontece que também tem 19 bytes.



2

Retina ,  44  23 bytes

Requer muita memória para executar para grandes valores de entrada. Converte em unário, depois divide repetidamente por 2, contando quantas vezes até atingir zero. A contagem de bytes assume a codificação ISO 8859-1.

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

Experimente online


11
Não tenho certeza se isso é válido. Este não é um caso de "requer mais memória do que você provavelmente terá", mas "requer mais memória do que a própria Retina pode suportar". Em particular, a conversão inicial para unária falhará para entradas da ordem 2 ^ 30 e acima, devido a limitações na implementação de Retina.
Martin Ender

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.