Tôi phù hợp với bao nhiêu bit


52

Đối với bất kỳ số nguyên 32 bit dương ( 1 ≤ n ≤ 0xFFFFFFFF) nào, số lượng bit cần thiết để biểu diễn số nguyên đó.

Các trường hợp thử nghiệm

| 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

Vì vậy, f(16)sẽ in hoặc trả lại5

Đây là . Mã ngắn nhất tính bằng byte


2
Đây là trần của logarit cơ sở-2.
orlp

23
@orlp Nó thực sự làfloor(log2(num))+1
Kritixi Lithos

2
@KritixiLithos Phải.
orlp

3
Nevermind, chỉ nhận ra rằng sự khác biệt là quan trọng khi numlà một sức mạnh của hai.
Brian J

11
Đây là một thách thức không đáng kể với rất nhiều giải pháp tầm thường. Tuy nhiên, có một số giải pháp không tầm thường. Đối với cử tri: Vui lòng đọc câu đầu tiên của bài đăng meta này trước khi nâng cao chức năng dựng sẵn. (khiêm tốn lấy từ nhận xét này )
Kritixi Lithos

Câu trả lời:


30

16
Ngôn ngữ bí truyền đã chiến thắng một lần nữa ...bg
devR Rich

20
@devR Rich Tôi hy vọng sẽ vẫn bị đánh bại bởi giải pháp 1 byte, thành thật mà nói.
Bạch tuộc ma thuật Urn

9
Ít nhất câu trả lời này được nó nâng cấp; nó không phải trong bg.
NoOneIsHãy

3
bgtrong chơi game có nghĩa là bad game:)
YoYoYonnY

1
@yoyoyonny hay chiến trường haha.
Bạch tuộc ma thuật Urn

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>


Đây là một trong số ít giải pháp không tầm thường ở đây. Chiến thuật tốt đẹp!
Kritixi Lithos

1
Có nên n>>>1hỗ trợ n > 0x7FFFFFFF?
Arnauld

@Arnauld Hmm, không biết >>đã thất bại ở nmức cao đó. Cảm ơn.
Sản phẩm ETH

Thật tuyệt, nỗ lực đầu tiên của tôi làf=(a,b=1)=>a>1?f(a>>1,++b):b
Bassdrop Cumberwubwubwub

28

Hội x86, 4 byte

Giả sử không đổi trong EBX:

bsr eax,ebx
inc eax

EAX chứa số bit cần thiết cho Constant.

Byte: ☼¢├@

Hệ thập lục phân: ['0xf', '0xbd', '0xc3', '0x40']


2
Bạn có thể vui lòng bao gồm một hexdump của mã hội x86 được biên dịch 8 byte thực tế không?
Loovjo

Đã làm như vậy. Và cảm ơn bạn, vì tôi nhận ra mình đã phạm sai lầm. Tôi đã thêm một "inc eax" để phù hợp với các quy tắc. Tôi đã mất một byte. :(
z0rberg

Oh wow bạn đã thay đổi bài viết của tôi để định dạng thích hợp. Cảm ơn đã sửa nó!
z0rberg

2
Nhân tiện, đệ trình hội có thể giả định rằng đầu vào đã được lưu trữ trong một thanh ghi cụ thể , vì vậy tôi nghĩ rằng bạn có thể cạo một vài byte theo cách đó.
Loovjo

1
Có phải là thông lệ để đếm đệ trình lắp ráp là số byte của mã máy được biên dịch thay vì mã nguồn ngôn ngữ lắp ráp?
mỉm cười

18

Python , 14 byte

int.bit_length

Hãy thử trực tuyến!


Nó cũng hoạt động trong Python 2.
vaultah

1
Nó thực sự. Quên Python 2 int rộng 64 bit, không phải 32 bit.
Dennis

Python 3 bit_lengthbit_length().
dfer Nam

2
@dfernan Đây không phải là một chức năng gọi; đó là một chức năng. Nếu n là một int , int.bit_length(n)n.bit_length()làm giống hệt nhau.
Dennis

2
@dfernan int.bit_length(n)là một lệnh gọi hàm và do đó, một đoạn mã giả định đầu vào được lưu trữ trong một biến. Điều này không được phép bởi các quy tắc của chúng tôi, vì vậy việc thêm vào (n)sẽ khiến câu trả lời này không hợp lệ. Tuy nhiên, int.bit_lengthđánh giá một hàm và có thể được lưu trong một biến để sử dụng sau. Điều này được cho phép theo mặc định.
Dennis

15

Mê cung , 13 12 byte

 ?
_:
2/#(!@

Hãy thử trực tuyến!

Giải trình

Chương trình chỉ đơn giản là liên tục chia đầu vào cho 2 cho đến khi bằng không. Số lượng các bước được theo dõi bằng cách nhân đôi giá trị ở mỗi bước. Khi nó giảm xuống 0, chúng tôi sẽ in độ sâu ngăn xếp (trừ 1).

Chương trình bắt đầu tại ?đó đọc đầu vào. Vòng lặp chính sau đó là khối 2x2 bên dưới, đi ngược chiều kim đồng hồ:

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

Khi giá trị bằng 0 sau khi lặp lại đầy đủ, bit tuyến tính ở cuối được thực thi:

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

5
Giải pháp này đã hoàn tất - cần có đầu vào và cung cấp câu trả lời, và không sử dụng bất kỳ chức năng hiện có nào cho mục đích cụ thể này - nó tính toán câu trả lời theo cách thủ công. Đối với tôi điều này là trên tinh thần của trò chơi hơn hầu hết các câu trả lời khác.
Johan

15

C, 31 byte

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

... Sau đó tôi nghĩ về đệ quy. Từ tối nghĩa đến rõ ràng, và với một phần tư chiều dài giảm xuống.

Xem nó trực tiếp trên Coliru


C, 43 byte

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

Gọi fvới giá trị không dấu (ví dụ f(42u)) sẽ "trả về" độ dài bit của nó. Thậm chí làm việc cho 0u!

Ungolfed và giải thích: (bỏ qua dấu gạch chéo ngược)

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

Xem nó trực tiếp trên Coliru


OP đảm bảo n> = 1, vì vậy n?...:0không cần thiết.
Nhà vật lý điên

1
@MadPhysicist, tôi phải dừng việc đệ quy ở đâu đó, không phải tôi;)
Quentin

OIC. Không đọc kỹ, cảm thấy như một thằng ngốc bây giờ. Trả lời gọn gàng một trong hai cách.
Nhà vật lý điên

@MadPhysicist không phải lo lắng, cảm ơn bạn rất nhiều :)
Quentin

Đối với giải pháp không đệ quy giả sử biểu thức câu lệnh gcc, tôi cho rằng bạn có thể đã có xu hướng sử dụng #define f(n) ({64-__builtin_clzl(n);})cách tiếp cận này.
Moreaki

14

Toán học, 9 byte

BitLength

Cách khác:

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

14

Perl 6 , 7 byte

*.msb+1

Thử nó

Giải trình:

* làm cho nó trở thành một lambda AnyCode và cho biết nơi để đặt đầu vào

.msb trên một Int trả về chỉ số của bit có ý nghĩa nhất (dựa trên 0)

+1được kết hợp vào lambda và thêm một kết quả cuối cùng của cuộc gọi .msb.



12

Võng mạc , 56 37 byte

Giải pháp này hoạt động với tất cả các giá trị đầu vào cần thiết.

Vấn đề lớn nhất mà Retina gặp phải trong thử thách này là thực tế là các chuỗi của nó có độ dài tối đa là 2 ^ 30 ký tự, do đó, cách xử lý thông thường với các số (biểu diễn đơn nhất) không hoạt động với các giá trị lớn hơn 2 ^ 30.

Để giải quyết vấn đề này, tôi đã thông qua một cách tiếp cận khác, giữ một loại đại diện thập phân của số, nhưng trong đó mỗi chữ số được viết bằng unary (Tôi sẽ gọi đại diện này digitunary ). Ví dụ, số 341sẽ được viết dưới dạng 111#1111#1#số. Với biểu diễn này, giờ đây chúng ta có thể làm việc với số lượng lên đến 2^30/10chữ số (~ một trăm triệu chữ số). Nó ít thực tế hơn so với unary tiêu chuẩn cho số học tùy ý, nhưng với một chút nỗ lực, chúng tôi có thể thực hiện bất kỳ loại hoạt động nào.

LƯU Ý: về mặt lý thuyết, số hóa có thể sử dụng bất kỳ cơ sở nào khác (ví dụ: nhị phân 110sẽ 1#1##ở cơ sở số 2), nhưng vì Retina đã tích hợp để chuyển đổi giữa số thập phân và đơn nguyên và không có cách nào trực tiếp để xử lý các cơ sở khác, nên số thập phân có thể là cơ sở dễ quản lý nhất.

Thuật toán tôi đã sử dụng đang thực hiện chia hai số nguyên liên tiếp cho đến khi chúng tôi đạt đến 0, số lượng phân chia chúng tôi thực hiện là số bit cần thiết để biểu diễn số này.

Vì vậy, làm thế nào để chúng ta chia cho hai trong số hóa? Đây là đoạn Retina thực hiện điều đó:

(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

Sự thay thế này là đủ để chia một số kỹ thuật số cho 2, chúng ta chỉ cần loại bỏ 0,5 giây có thể từ cuối nếu số ban đầu là số lẻ.

Vì vậy, đây là mã đầy đủ, chúng tôi tiếp tục chia cho hai cho đến khi vẫn còn các chữ số trong số và đặt một chữ nđứng trước chuỗi ở mỗi lần lặp: số nở cuối là kết quả.

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

Hãy thử trực tuyến!


Giải pháp cập nhật, 37 byte

Tái cấu trúc lớn với nhiều ý tưởng hay, đánh golf khoảng một phần ba chiều dài, tất cả là nhờ Martin Ender!

Ý tưởng chính là sử dụng _làm biểu tượng đơn nguyên của chúng tôi: bằng cách này, chúng tôi có thể sử dụng các chữ số thông thường trong chuỗi của mình, miễn là chúng tôi chuyển đổi chúng thành _s khi cần: điều này cho phép chúng tôi lưu nhiều byte khi chia và chèn nhiều chữ số.

Đây là mã:

<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

Hãy thử trực tuyến!


1
Tôi đã sử dụng một dạng số tương tự (nhưng được gọi là Số thập phân Unary-Coded ), khá tiện cho số học với Sed.
Toby Speight

11

Ruby, 19 16 byte

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

Cảm ơn Jordan vì đã chơi golf 3 byte


Bạn có thể lưu một byte với %: ->n{("%b"%n).size}.
Jordan

3
Chờ đã, đây là ngắn hơn: ->n{"%b"%n=~/$/}.
Jordan

10

Jolf, 2 byte

lB

Chỉ cần chuyển đổi thành nhị phân và sau đó tìm độ dài.



10

JavaScript ES6, 19 byte

a=>32-Math.clz32(a)

Math.clz32trả về số bit 0 hàng đầu trong biểu diễn nhị phân 32 bit của một số. Vì vậy, để có được số lượng bit cần thiết, tất cả những gì chúng ta cần làm là trừ số đó từ 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
Sự thay thế a=>1+Math.log2(a)|0cũng là 19 byte.
Neil

5
@Neil 1+...|0hét lên trừ dấu ngã ! a=>-~Math.log2(a)là 18
edc65

@ edc65 Tôi đếm 17 ... nhưng vâng, tôi chắc chắn mình đã bỏ lỡ điều gì đó, cảm ơn vì đã chỉ ra.
Neil

@Neil Hãy đăng bài dưới dạng câu trả lời riêng biệt. Nó sử dụng một phương thức khác với câu trả lời của tôi, vì vậy sẽ cảm thấy không công bằng khi sử dụng của bạn để giảm số byte
Bassdrop Cumberwubwubwub

10

công cụ bash / Unix, 16 byte

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

Lưu cái này trong một tập lệnh và truyền đầu vào dưới dạng đối số. Số lượng bit cần thiết để thể hiện số đó trong nhị phân sẽ được in.

Đây là một lời giải thích:

dc là một máy tính dựa trên ngăn xếp. Đầu vào của nó, được phân tích thành các mã thông báo, là:

2 - Đẩy 2 trên ngăn xếp.

o - Pop một giá trị ra khỏi ngăn xếp (là 2) và biến nó thành cơ sở đầu ra (vì vậy đầu ra bây giờ ở dạng nhị phân).

Giá trị của đối số cho chương trình bash ($ 1) - Đẩy đối số đó lên ngăn xếp.

n - Bỏ giá trị ra khỏi ngăn xếp (là số đầu vào) và in nó (ở dạng nhị phân, vì đó là cơ sở đầu ra) không có dòng mới.

Vì vậy, lệnh dc in số ở dạng nhị phân.

Đầu ra của dc được dẫn đến lệnh wc với tùy chọn -c, in số lượng ký tự trong đầu vào của nó.

Kết quả cuối cùng là in số chữ số trong biểu diễn nhị phân của đối số.


Lựa chọn tốt về ngôn ngữ, nhưng sẽ còn tuyệt hơn nữa nếu bạn đưa ra một lời giải thích.
NH.

@NH Cảm ơn. Tôi đã thêm một lời giải thích.
Spector Mitchell

9

Google Sheets, 15 byte

Đưa đầu vào từ ô A1và xuất ra ô chứa công thức

=Len(Dec2Bin(A1

hoặc là

=Int(1+Log(A1,2

hoặc là

=Int(Log(2*A1,2

Excel, 17 byte

Tương tự như trên nhưng được định dạng cho MS Excel

=Len(Dec2Bin(A1))

hoặc là

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

hoặc là

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


8

Thạch, 2 byte

BL

Chuyển đổi thành nhị phân, tìm độ dài.


8

C #, 63 45 31 byte

Đã lưu 18 byte, nhờ Loovjo và TuukkaX

Đã lưu 14 byte, nhờ Grax

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

Nó sử dụng, đó là một số thập phân n có ⌊log2 (n) ⌋ + 1 bit, được mô tả trên đây trang:

Số bit trong một số nguyên thập phân cụ thể

Một số nguyên dương n có b bit khi 2 ^ (b - 1) ≤ n 2 ^ b - 1. Ví dụ:

  • 29 có 5 bit vì 16 29 31 hoặc 2 ^ 4 29 ≤ 2 ^ 5 - 1
  • 123 có 7 bit vì 64 123 ≤ 127 hoặc 2 ^ 6 123 ≤ 2 ^ 7 - 1
  • 967 có 10 bit vì 512 967 1023 hoặc 2 ^ 9 967 2 ^ 10 - 1

Đối với số lượng lớn hơn, bạn có thể tham khảo bảng quyền hạn của hai để tìm các quyền hạn liên tiếp có chứa số của bạn.

Để xem lý do tại sao điều này hoạt động, hãy nghĩ đến các biểu diễn nhị phân của các số nguyên 2 ^ 4 đến 2 ^ 5 - 1 chẳng hạn. Chúng là 10000 đến 11111, tất cả các giá trị 5 bit có thể.

Sử dụng logarit

Phương pháp trên có thể được nói theo một cách khác: số bit là số mũ của công suất nhỏ nhất bằng hai số lớn hơn số của bạn. Bạn có thể nói rằng về mặt toán học là:

bspec = ⌊log2 (n) + 1

Công thức đó có ba phần:

  • log2 (n) có nghĩa là logarit trong cơ sở 2 của n, là số mũ mà 2 được nâng lên để lấy n. Ví dụ: log2 (123) ≈ 6,9425145. Sự hiện diện của một phần phân số có nghĩa là n nằm giữa quyền hạn của hai.

  • X⌋ là sàn của x, là phần nguyên của x. Ví dụ: .96.9425145⌋ = 6. Bạn có thể nghĩ log2 (n) ⌋ là số mũ của công suất cao nhất của hai trong biểu diễn nhị phân của n.

  • +1 lấy số mũ cho lũy thừa cao hơn tiếp theo của hai. Bạn có thể nghĩ về bước này khi chiếm vị trí thứ 2 ^ 0 của số nhị phân của bạn, sau đó cung cấp cho bạn tổng số bit của nó. Ví dụ của chúng tôi, đó là 6 + 1 = 7. Bạn có thể muốn sử dụng hàm trần - ⌈x⌉, là số nguyên nhỏ nhất lớn hơn hoặc bằng x - để tính số bit như vậy:

bspec = ⌈log2 (n)

Tuy nhiên, điều này thất bại khi n là một sức mạnh của hai.


Bạn có thêm một không gian trong đó ...)+ 1)...-> ...)+1.... Ngoài ra, tôi nghĩ rằng bạn có thể trả lại giá trị trực tiếp thay vì in nó.
Loovjo

Bạn có thể giảm xuống còn 31 bằng cách thực hiện b=>1+(int)System.Math.Log(b,2); Chuyển đổi int cung cấp cùng một đầu ra như Math.Floor và bạn không cần sử dụng câu lệnh nếu bạn chỉ tham chiếu Hệ thống một lần.
Grax32

6

C #, 32 byte

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

Chuyển đổi tham số thành chuỗi nhị phân và trả về độ dài của chuỗi.


4

Haskell, 20 byte

succ.floor.logBase 2

Kết hợp một hàm lấy logarit cơ sở 2, tầng và thêm 1.


4

Befunge-93 , 23 21 byte

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

Befunge là ngôn ngữ dựa trên lưới 2D (mặc dù tôi chỉ sử dụng một dòng).

&                      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

Hãy thử trực tuyến!


@JamesHoldiness Cảm ơn, tôi đoán rằng nó có thể được rút ngắn vì nó có quá nhiều hàm băm / dấu cách, nhưng tôi không thể hiểu được.
JayDepp





3

QBIC , 18 byte

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

Thật không thể tin được Mike! Nhưng làm thế nào nó hoạt động?

:        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

Octave, 19 byte

@(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 có hai chức năng để chuyển đổi số thập phân thành số nhị phân.

dec2binchuyển đổi một số thành một chuỗi các ký tự 10(giá trị ASCII 4849). Độ dài của chuỗi sẽ bằng với số bit cần thiết, trừ khi có quy định khác. Vì các ký tự 10khác không, chúng ta có thể sử dụng nnzđể tìm số phần tử như thế này : @(x)nnz(dec2bin(x)). Đây là 19 byte, vì vậy nó được liên kết với câu trả lời Octave khác của Luis Mendo .

Chúng ta có thể làm tốt hơn bằng cách sử dụng de2bi?

de2bilà một hàm trả về các số nhị phân dưới dạng một vectơ với các số 10dưới dạng số nguyên, không phải là ký tự. de2birõ ràng là ngắn hơn hai byte dec2bin, nhưng chúng ta không thể sử dụng nữa nnz. Chúng ta có thể sử dụng nnznếu chúng ta thêm 1vào tất cả các phần tử hoặc biến nó thành một vectơ logic chỉ có truecác giá trị. @(x)nnz(de2bi(x)+1)@(x)nnz(de2bi(x)<2)là cả 19 byte. Sử dụng numelcũng sẽ cung cấp cho chúng tôi 19 byte,@(x)numel(de2bi(x)) ,.

rowsngắn hơn một byte numel, nhưng de2bitrả về một vectơ ngang, do đó nó phải được hoán vị. @(x)rows(de2bi(x)')chỉ xảy ra là 19 byte.



2

Võng mạc ,  44  23 byte

Yêu cầu quá nhiều bộ nhớ để chạy cho các giá trị đầu vào lớn. Chuyển đổi thành unary, sau đó liên tục chia cho 2, đếm bao nhiêu lần cho đến khi nó bằng không. Số lượng byte giả định mã hóa ISO 8859-1.

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

Dùng thử trực tuyến


1
Tôi không chắc điều này là hợp lệ. Đây không phải là trường hợp "nó đòi hỏi nhiều bộ nhớ hơn bạn có thể có" nhưng "nó đòi hỏi nhiều bộ nhớ hơn bản thân Retina có thể xử lý". Cụ thể, việc chuyển đổi ban đầu thành đơn nguyên sẽ thất bại đối với các đầu vào của đơn hàng 2 ^ 30 trở lên, do những hạn chế trong việc triển khai của Retina.
Martin Ender

Nếu nó hợp lệ, nó có thể được rút ngắn rất nhiều mặc dù: tio.run/nexus/retina#@6@nxaWixaWdEKdhqK1paB9jyKViGM@l9/@/saUhAA
Martin Ender
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.