몇 비트에 맞습니까?


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

3
단지 num2의 거듭 제곱 일 때 그 구별이 중요하다는 것을 깨달았습니다 .
Brian J

11
이것은 많은 사소한 해결책으로 사소한 도전입니다. 그러나 사소한 해결책도 있습니다. 유권자에게 : 내장 함수 를 찬성 하기 전에이 메타 포스트첫 문장을 읽으십시오 . (이 코멘트 에서 겸손하게 )
Kritixi Lithos

답변:



35

자바 스크립트 (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>


이것은 몇 가지 사소한 해결책 중 하나입니다. 좋은 전술!
Kritixi Lithos

1
n>>>1지원 해야합니까 n > 0x7FFFFFFF?
Arnauld

@Arnauld 흠, 그 높은 >>실패를 몰랐어요 n. 감사.
ETHproductions

니스, 내 첫 시도는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의

와우 내 게시물을 올바른 형식으로 변경했습니다. 수정 해 주셔서 감사합니다!
z0rberg의

2
그런데 어셈블리 제출은 입력이 이미 특정 레지스터에 저장되어 있다고 가정 할 수 있으므로 그런 식으로 몇 바이트를 줄일 수 있다고 생각합니다.
Loovjo

1
어셈블리 제출을 어셈블리 언어 소스 코드가 아닌 컴파일 된 기계 코드의 바이트 수로 계산하는 것이 관례입니까?
smls

18

파이썬 , 14 바이트

int.bit_length

온라인으로 사용해보십시오!


파이썬 2에서도 작동합니다.
vaultah

1
실제로 그렇습니다. Python 2의 정수 는 32 비트가 아닌 64 비트 너비였습니다.
Dennis

파이썬 3은 bit_length입니다 bit_length().
dfernan

2
@dfernan 이것은 함수 호출이 아닙니다. 그것은 기능입니다. 경우 , n은 이다 INT , int.bit_length(n)그리고 n.bit_length()정확히 같은 않습니다.
Dennis

2
@dfernan int.bit_length(n)은 함수 호출 이므로 입력이 변수에 저장되어 있다고 가정하는 스 니펫입니다. 이는 Google 규칙에서 허용 되지 않으므로 추가 (n)하면이 답변이 유효하지 않게됩니다. 그러나 int.bit_length함수로 평가되며 나중에 사용하기 위해 변수에 저장할 수 있습니다. 기본적으로 허용됩니다.
Dennis

15

미로 , 13 12 바이트

 ?
_:
2/#(!@

온라인으로 사용해보십시오!

설명

프로그램은 단순히 0이 될 때까지 입력을 2로 반복해서 나눕니다. 각 단계에서 값을 복제하여 단계 수를 추적합니다. 일단 0으로 줄이면 스택 깊이 (-1)를 인쇄합니다.

?입력을 읽는 프로그램이 시작됩니다 . 메인 루프는 시계 반대 방향으로 아래 2x2 블록입니다.

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

전체 반복 후 값이 0이면 끝에있는 선형 비트가 실행됩니다.

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

5
이 솔루션은 완전합니다. 입력을 받고 답변을 제공하며이 특정 목적을 위해 기존 기능을 사용하지 않습니다-답변을 수동으로 계산합니다. 나에게 이것은 대부분의 다른 답변보다 게임 정신에 더 가깝습니다.
Johan

15

C, 31 바이트

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

... 그런 다음 재귀에 대해 생각했습니다. 모호한 것에서 명백한 것까지, 길이의 4 분의 1이 빠졌습니다.

콜리 루에서 생방송보기


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

콜리 루에서 생방송보기


OP는 n> = 1을 보장하므로 n?...:0필요하지 않습니다.
Mad Physicist

1
@MadPhysicist 잘 나는 어딘가에 재귀를 중지해야합니다, 난하지 않습니다;)
Quentin

OIC. 주의 깊게 읽지 않았고 지금 바보 같은 기분이 들었습니다. 깔끔한 대답.
Mad Physicist

@MadPhysicist 걱정하지 마세요, 대단히 감사합니다 :)
Quentin

gcc 문 표현을 가정하는 비 재귀 솔루션의 경우 #define f(n) ({64-__builtin_clzl(n);})접근법 을 사용하는 경향이 있다고 생각합니다 .
Moreaki


14

펄 6 , 7 바이트

*.msb+1

시도 해봐

설명:

* WhateverCode 람다가되고 입력을 넣을 위치를 나타냅니다.

.msb Int는 최상위 비트의 인덱스를 반환합니다 (0 기반).

+1는 람다로 결합되고을 호출 한 최종 결과에 하나를 추가합니다 .msb.


13

C 전 처리기 매크로 (gcc 확장자 포함), 26

#define f 32-__builtin_clz

GCC의 카운트 제로 제로 내장을 사용 합니다.

이를 함수로 호출하십시오 (예 :) f(100).

온라인으로 사용해보십시오 .


와우, 나는 내장을 사용하는 것에 대해 생각했지만 너무 오래 될 것이라고 생각했기 때문에 아이디어를 떨어 뜨렸다 ... 잘 연주했다.
Quentin

운이 좋은 OP 지정 n> = 1 : D
Matthieu M.

12

망막 , 56 37 바이트

이 솔루션은 필요한 모든 입력 값으로 작동합니다.

이 과제에서 Retina가 직면하는 가장 큰 문제는 문자열의 최대 길이가 2 ^ 30 자이므로 숫자를 처리하는 일반적인 방법 (단항 표현)이 2 ^ 30보다 큰 값에서는 작동하지 않는다는 것입니다.

이 문제를 해결하기 위해 숫자의 소수 표현을 유지하면서 각 숫자가 단항으로 쓰여지는 다른 접근법을 채택했습니다 (이 표현을 digitunary 라고 부릅니다 ). 예를 들어 숫자 341111#1111#1#digitunary 로 기록됩니다 . 이 표현으로 우리는 이제 최대 2^30/10자릿수 (~ 1 억 자릿수)로 작업 할 수 있습니다 . 임의의 산술에 대해서는 표준 단항보다 실용적이지 않지만 약간의 노력으로 모든 종류의 작업을 수행 할 수 있습니다.

참고 : 이론상 digitunary는 다른 기수를 사용할 수 있지만 (예 : 2 진 1101#1##기수 2 digitunary 일 수 있음) Retina는 십진법과 단 항법 사이를 변환 할 수있는 내장 기능이 있으며 다른 염기를 처리하는 직접적인 방법이 없기 때문에 십진법이 가장 관리하기 쉬운 염기 서열 일 것입니다.

내가 사용한 알고리즘은 0에 도달 할 때까지 연속적인 정수 나누기를 2 씩 만드는 것입니다. 나누기 수는이 숫자를 나타내는 데 필요한 비트 수입니다.

그렇다면 어떻게 digitunary에서 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

이 대체는 digitunary 숫자를 2로 나누기에 충분합니다. 원래 숫자가 홀수 인 경우 가능한 0.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 바이트

Martin Ender 덕분에 길이의 약 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
비슷한 숫자 형식 (그러나 Unary-Coded Decimal 이라고 함 )을 사용했는데 Sed로 산술하는 데 매우 편리합니다.
Toby Speight

11

루비, 19 16 바이트

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

3 바이트를 포기한 Jordan에게 감사합니다


당신은으로 바이트를 저장할 수 있습니다 %: ->n{("%b"%n).size}.
Jordan

3
잠시만 기다려주세요 ->n{"%b"%n=~/$/}..
Jordan

10

줄프, 2 바이트

lB

이진으로 변환 한 다음 길이를 찾으십시오.



10

자바 스크립트 ES6, 19 바이트

a=>32-Math.clz32(a)

Math.clz32숫자의 32 비트 이진 표현에서 선행 0 비트의 수를 반환합니다. 따라서 필요한 비트 수를 얻으려면 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 바이트입니다.
Neil

5
@Neil은 물결표를 뺀1+...|0 소리를 냅니다 ! a=>-~Math.log2(a)
37에

@ 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 감사합니다. 설명을 추가했습니다.
Mitchell Spector

9

Google 스프레드 시트, 15 바이트

셀에서 입력을 가져 와서 A1수식을 보유한 셀로 출력

=Len(Dec2Bin(A1

또는

=Int(1+Log(A1,2

또는

=Int(Log(2*A1,2

엑셀, 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);

또한, 사용하는 십진수 N에 기술된다 ⌊log2 (N) ⌋ + 1 비트를 갖는 이러한 페이지 :

특정 십진 정수의 비트 수

양의 정수 n은 2 ^ (b-1) ≤ n ≤ 2 ^ b – 1 일 때 b 비트를 갖습니다. 예를 들면 다음과 같습니다.

  • 29는 16 ≤ 29 ≤ 31 또는 2 ^ 4 ≤ 29 ≤ 2 ^ 5 – 1이므로 5 비트를 갖습니다.
  • 123은 64 ≤ 123 ≤ 127 또는 2 ^ 6 ≤ 123 ≤ 2 ^ 7 – 1이므로 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

이 공식에는 세 부분이 있습니다.

  • log2 (n)은 n의 밑이 2 인 로그를 의미하며, 이는 2가 n을 얻기 위해 증가하는 지수입니다. 예를 들어, log2 (123) ≈ 6.9425145입니다. 분수 부분 수단 n의 존재는 2의 거듭 제곱 사이입니다.

  • ⌊x⌋는 x의 바닥이며 x의 정수 부분입니다. 예를 들어, ⌊6.9425145⌋ = 6입니다. n의 이진 표현에서 oflog2 (n) ⌋을 2의 최대 거듭 제곱의 지수로 생각할 수 있습니다.

  • +1은 지수를 2의 다음으로 거듭 제곱합니다. 이 단계를 이진수의 2 ^ 0 번째 자리를 고려한 것으로 생각하면 총 비트 수를 얻을 수 있습니다. 이 예에서는 6 + 1 = 7입니다. 비트 수를 계산하기 위해 천장 함수 (x보다 크거나 같은 가장 작은 정수인 ⌈x⌉)를 사용하고 싶을 수 있습니다.

bspec = ⌈log2 (n) ⌉

그러나 n이 2의 거듭 제곱 인 경우 실패합니다.


거기에 여분의 공간이 있습니다 ...)+ 1)...-> ...)+1.... 또한 값을 인쇄하지 않고 직접 반환 할 수 있다고 생각합니다.
Loovjo

당신은 수행하여 31 내려 놓을 수 b=>1+(int)System.Math.Log(b,2); Math.Floor과 같은 출력을 INT 변환을 제공하고 한 번만 시스템을 참조하는 경우에는 사용하여 문을 필요가 없습니다.
Grax32

6

C #, 32 바이트

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

매개 변수를 이진 문자열로 변환하고 문자열의 길이를 반환합니다.


4

하스켈, 20 바이트

succ.floor.logBase 2

로그베이스 2, 플로어를 취하고 1을 더하는 함수를 작성합니다.


4

Befunge-93 , 23 21 바이트

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

Befunge는 2D 그리드 기반 언어입니다 (단 한 줄만 사용하고 있지만).

&                      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





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

옥타브에는 10 진수를 이진수로 변환하는 두 가지 기능이 있습니다.

dec2bin숫자를 문자열 10(ASCII- 값 4849)로 변환합니다. 달리 지정하지 않는 한 문자열의 길이는 필요한 비트 수와 같습니다. 문자가 있기 때문에 100이 아닌, 우리가 사용할 수있는 nnz이 같은 요소의 수를 확인하는 방법은 다음과 같습니다 @(x)nnz(dec2bin(x)). 이것은 19 바이트이므로 Luis Mendo의 다른 Octave 답변 과 묶여 있습니다.

더 잘 사용할 수 de2bi있습니까?

de2bi숫자와 벡터로 진수를 반환하는 함수 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로 나누고 0에 도달 할 때까지 몇 번이나 계산합니다. 바이트 수는 ISO 8859-1 인코딩을 가정합니다.

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

온라인으로 사용해보십시오


1
이것이 유효한지 확실하지 않습니다. "아마도 더 많은 메모리가 필요하다"는 것은 아니지만 "Retina 자체가 처리 할 수있는 것보다 더 많은 메모리가 필요합니다"의 경우는 아닙니다. 특히, Retina의 구현 제한으로 인해 2 ^ 30 이상의 주문에서는 단항으로의 초기 변환이 실패합니다.
Martin Ender

그것이 유효하다면, 그것은 많이 단축 될 수 있습니다 : tio.run/nexus/retina#@6@nxaWixaWdEKdhqK1paB9jyKViGM@l9/@/saUhAA
Martin Ender
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.