C # nhị phân


186

Có cách nào để viết các chữ nhị phân trong C #, như tiền tố thập lục phân với 0x không? 0b không hoạt động.

Nếu không, một cách dễ dàng để làm điều đó là gì? Một số loại chuyển đổi chuỗi?


2
Sử dụng các hằng số và đặt cho chúng tên thích hợp, sau đó thực tế là bạn phải viết chúng ra dưới dạng thập phân không quan trọng. Cá nhân tôi muốn đọc if (a == MaskForModemIOEnabled)hơn làif (a == 0b100101)
Lasse V. Karlsen

1
Một lưu ý khác: Nếu bạn tìm thấy bài đăng này vì bạn muốn có một trường bit, vui lòng xem xét thuộc tính flags: msdn.microsoft.com/en-us/l
Library / cc138362.aspx#sectionToggle0

16
Cả hai lời khuyên rất tốt, ngoại trừ khi định nghĩa các bitfield đã nói, trong đó các định nghĩa hằng được đặt tên này có thể dễ đọc và viết hơn với một chữ nhị phân. [Flags] enum Số lượng {Không = 0, One = 1, Một số = 0b10, Hầu hết = 0b100, tất cả = 0b111}
brianary

1
Đối với những gì nó có giá trị, hỗ trợ cho chữ nhị phân được lên kế hoạch cho Roslyn .
Joe White

Nó vẫn chưa được hỗ trợ trong C # 6.0, phải không? Không thể sử dụng chữ nhị phân trong vs2015: /
anhoppe

Câu trả lời:


145

C # 7.0 hỗ trợ chữ nhị phân (và dấu tách chữ số tùy chọn thông qua các ký tự gạch dưới).

Một ví dụ:

int myValue = 0b0010_0110_0000_0011;

Bạn cũng có thể tìm thêm thông tin trên trang Roslyn GitHub .


3
@ D.Singh Tôi thấy nó trong danh sách C # 7 bây giờ. github.com/dotnet/roslyn/issues/2136
Danation

9
Ngọt! Làm việc tuyệt vời trong VS2017 / C # 7.
STLDev

1
Điều này giúp ghi nhớ rằng Văn học nhị phân của C # là lớn về cuối, nhưng trên số nguyên x86 là số ít về cuối, do đó Int16 = 0b0010_0110_0000_0011sẽ được lưu trữ dưới dạng { 0b0000_0011, 0b0010_0110 }- gây nhầm lẫn.
Đại

1
@Dai không khác gì chữ hex. Nói cách khác, tất cả các hằng số đều là endian lớn, nhưng được lưu trữ ít endian trên Intel / AMD và hầu hết các ARM. 0xDEADBEEFsẽ được lưu trữ dưới dạng0xEF 0xBE 0xAD 0xDE
Cole Johnson

168

Cập nhật

C # 7.0 hiện có chữ nhị phân, thật tuyệt vời.

[Flags]
enum Days
{
    None = 0,
    Sunday    = 0b0000001,
    Monday    = 0b0000010,   // 2
    Tuesday   = 0b0000100,   // 4
    Wednesday = 0b0001000,   // 8
    Thursday  = 0b0010000,   // 16
    Friday    = 0b0100000,   // etc.
    Saturday  = 0b1000000,
    Weekend = Saturday | Sunday,
    Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday
}

Bài gốc

Vì chủ đề dường như đã chuyển sang khai báo các giá trị cờ dựa trên bit trong enums, tôi nghĩ rằng sẽ rất đáng để chỉ ra một mẹo hữu ích cho loại điều này. Toán tử shift trái ( <<) sẽ cho phép bạn đẩy một chút đến vị trí nhị phân cụ thể. Kết hợp điều đó với khả năng khai báo các giá trị enum theo các giá trị khác trong cùng một lớp và bạn có một cú pháp khai báo rất dễ đọc cho các enum cờ bit.

[Flags]
enum Days
{
    None        = 0,
    Sunday      = 1,
    Monday      = 1 << 1,   // 2
    Tuesday     = 1 << 2,   // 4
    Wednesday   = 1 << 3,   // 8
    Thursday    = 1 << 4,   // 16
    Friday      = 1 << 5,   // etc.
    Saturday    = 1 << 6,
    Weekend     = Saturday | Sunday,
    Weekdays    = Monday | Tuesday | Wednesday | Thursday | Friday
}

26
@ColeJohnson: Nhiều nhà phát triển thích điều đó. Tôi không giỏi chuyển đổi hex trong đầu như một số nhà phát triển, và đôi khi tốt nhất là phục vụ cho mẫu số chung thấp nhất.
StriplingWar Warrior

2
Tôi nghĩ rằng đây là cách hiệu quả nhất vì enums được xây dựng như hằng số. Với thuộc tính [Cờ] tùy chọn, chúng có thể được sử dụng trong các phép toán bitwise (không liên quan trực tiếp đến câu hỏi, nhưng đặc biệt hữu ích khi mô tả bằng chữ nhị phân). Một khả năng thú vị khác là buộc loại enum là loại tích hợp (trong ví dụ này, thêm ': byte' sau 'Days'); xem các loại tích hợp trong bit.ly/MKv42E
caligari

Điều đó thực sự rất dễ đọc, mặc dù việc tuyên bố cờ 0 trên Enum là một thực tế khá tệ
MikeT

5
@MikeT: Bạn có thể xây dựng (hoặc cung cấp một liên kết chi tiết) về ý nghĩ cuối cùng đó không? Tôi thường khai báo các enum bắt đầu bằng "1" vì tôi muốn có thể phát hiện và không nhanh khi một giá trị đơn giản là không bao giờ được khởi tạo. Nhưng có một số tình huống trong đó một giá trị mặc định thực sự có ý nghĩa và tôi nghĩ sẽ không có gì sai khi thêm tên cho giá trị đó.
StriplingWar Warrior

3
@MikeT Từ ca1008 : "Nếu một bảng liệt kê được áp dụng FlagsAttribution xác định một thành viên có giá trị bằng 0, tên của nó phải là 'Không' để chỉ ra rằng không có giá trị nào được đặt trong bảng liệt kê." Vì vậy, nó hoàn toàn hợp lệ để thêm nó làm giá trị mặc định, nếu nó được gọi là "Không". Nhìn chung, nó có vẻ sạch hơn đối với tôi nếu giá trị trong trường được khởi tạo mặc định thực sự có tên để hiển thị.
Nyerguds

115

Chỉ có số nguyên và hex trực tiếp, tôi sợ (ECMA 334v4):

9.4.4.2 Chữ số nguyên Chữ nguyên được sử dụng để viết các giá trị của các kiểu int, uint, long và ulong. Chữ nguyên có hai dạng có thể: thập phân và thập lục phân.

Để phân tích cú pháp, bạn có thể sử dụng:

int i = Convert.ToInt32("01101101", 2);

4
Là một bản cập nhật cho câu trả lời này, với thông tin hiện đại tiên tiến nhất (tháng 7 năm 2014); C # 6.0 giới thiệu chữ nhị phân. Xem câu trả lời cập nhật của tôi ở phía dưới ...
BTownTKD

1
@BTownTKD câu trả lời của bạn thực sự đứng đầu :) vì đó là câu trả lời được chấp nhận.
RBT

25

Thêm vào câu trả lời của @ StriplingWar Warrior về cờ bit trong enums, có một quy ước dễ dàng mà bạn có thể sử dụng theo hệ thập lục phân để đếm ngược lên trên qua các ca bit. Sử dụng chuỗi 1-2-4-8, di chuyển một cột sang trái và lặp lại.

[Flags]
enum Scenery
{
  Trees   = 0x001, // 000000000001
  Grass   = 0x002, // 000000000010
  Flowers = 0x004, // 000000000100
  Cactus  = 0x008, // 000000001000
  Birds   = 0x010, // 000000010000
  Bushes  = 0x020, // 000000100000
  Shrubs  = 0x040, // 000001000000
  Trails  = 0x080, // 000010000000
  Ferns   = 0x100, // 000100000000
  Rocks   = 0x200, // 001000000000
  Animals = 0x400, // 010000000000
  Moss    = 0x800, // 100000000000
}

Quét xuống bắt đầu với cột bên phải và chú ý mẫu 1-2-4-8 (ca) 1-2-4-8 (ca) ...


Để trả lời câu hỏi ban đầu, tôi đề nghị thứ hai @ Sahuagin sử dụng các chữ thập lục phân. Nếu bạn đang làm việc với các số nhị phân thường đủ để điều này trở thành mối quan tâm, thì đáng để bạn sử dụng hệ thập lục phân.

Nếu bạn cần xem số nhị phân trong mã nguồn, tôi khuyên bạn nên thêm nhận xét bằng chữ nhị phân như tôi có ở trên.


23

Bạn luôn có thể tạo các ký tự gần đúng, các hằng số chứa giá trị bạn theo sau:

const int b001 = 1;
const int b010 = 2;
const int b011 = 3;
// etc ...
Debug.Assert((b001 | b010) == b011);

Nếu bạn sử dụng chúng thường xuyên thì bạn có thể bọc chúng trong một lớp tĩnh để sử dụng lại.

Tuy nhiên, ngoài chủ đề, nếu bạn có bất kỳ ngữ nghĩa nào liên quan đến các bit (được biết tại thời điểm biên dịch), tôi sẽ đề nghị sử dụng Enum thay thế:

enum Flags
{ 
    First = 0,
    Second = 1,
    Third = 2,
    SecondAndThird = 3
}
// later ...
Debug.Assert((Flags.Second | Flags.Third) == Flags.SecondAndThird);

18

Nếu bạn xem trạng thái triển khai tính năng ngôn ngữ của Nền tảng trình biên dịch .NET ("Roslyn"), bạn có thể thấy rõ rằng trong C # 6.0, đây là một tính năng được lên kế hoạch, vì vậy trong phiên bản tiếp theo, chúng tôi có thể thực hiện theo cách thông thường.

Tình trạng nhị phân


3
Nó đã đến để vượt qua? Không phải tất cả các tính năng đã được viết về việc thực sự phát hành Visual Studio 2015.
Đại tá Panic

4
@ColonelPanic - Danation chỉ ra rằng đó là "thuộc danh mục C # 7 ngay bây giờ" - github.com/dotnet/roslyn/issues/2136
Wai Hà Lee

3
string sTable="static class BinaryTable\r\n{";
string stemp = "";
for (int i = 0; i < 256; i++)
{
stemp = System.Convert.ToString(i, 2);
while(stemp.Length<8) stemp = "0" + stemp;
sTable += "\tconst char nb" + stemp + "=" + i.ToString() + ";\r\n";
}
sTable += "}";
Clipboard.Clear();
Clipboard.SetText ( sTable);
MessageBox.Show(sTable);

Sử dụng cái này, đối với nhị phân 8 bit, tôi sử dụng cái này để tạo một lớp tĩnh và nó đặt nó vào bảng tạm .. Sau đó, nó được dán vào dự án và thêm vào phần Sử dụng, vì vậy mọi thứ với nb001010 đều được lấy ra khỏi một bảng, tại ít tĩnh nhất, nhưng vẫn ... Tôi sử dụng C # cho rất nhiều mã hóa đồ họa PIC và sử dụng 0b101010 rất nhiều trong Hi-Tech C

- mẫu từ mã outpt--

static class BinaryTable
{   const char nb00000000=0;
    const char nb00000001=1;
    const char nb00000010=2;
    const char nb00000011=3;
    const char nb00000100=4;
//etc, etc, etc, etc, etc, etc, etc, 
}

:-) CẦN


3

Tính năng nhị phân không được triển khai trong C # 6.0 & Visual Studio 2015. nhưng vào ngày 30 tháng 3 năm 2016, Microsoft đã công bố phiên bản mới của Visual Studio '15' Preview mà chúng ta có thể sử dụng các chữ nhị phân.

Chúng ta có thể sử dụng một hoặc nhiều ký tự gạch dưới (_) cho dấu tách chữ số. vì vậy đoạn mã sẽ trông giống như:

int x           = 0b10___10_0__________________00; //binary value of 80
int SeventyFive = 0B100_________1011; //binary value of 75

WriteLine($" {x} \n {SeventyFive}");

và chúng ta có thể sử dụng 0b và 0B như trong đoạn mã trên.

nếu bạn không muốn sử dụng dấu tách chữ số, bạn có thể sử dụng nó mà không cần dấu tách chữ số như đoạn mã dưới đây

int x           = 0b1010000; //binary value of 80
int SeventyFive = 0B1001011; //binary value of 75

WriteLine($" {x} \n {SeventyFive}");

2

Mặc dù không thể sử dụng bằng chữ, nhưng có lẽ BitConverter cũng có thể là một giải pháp?


BitConverter có một chút khó khăn vì nó là máy cuối; và trên Intel tiêu chuẩn của bạn, điều đó có nghĩa là endian nhỏ. Hầu hết mọi người đều gặp khó khăn trong việc đọc các văn chương cuối nhỏ ...
Marc Gravell

1
Ôi, bây giờ tôi nhớ tại sao tôi luôn biết nhưng không bao giờ sử dụng BitConverter ...
Michael Stum

4
BitConverter có trường BitConverter.IsLittleEndianmà bạn có thể sử dụng để kiểm tra (và đảo ngược bộ đệm) nếu máy chủ không có ít endian.
foxy

1

Mặc dù giải pháp phân tích cú pháp chuỗi là phổ biến nhất, tôi không thích nó, bởi vì chuỗi phân tích cú pháp có thể là một hiệu suất tuyệt vời trong một số trường hợp.

Khi cần một loại mặt nạ bitfield hoặc nhị phân, tôi muốn viết nó như thế

bitMask dài = 1011001;

Và sau đó

int bit5 = BitField.GetBit (bitMask, 5);

Hoặc là

cờ bool5 = BitField.GetFlag (bitMask, 5); `

Lớp BitField ở đâu

public static class BitField
{
    public static int GetBit(int bitField, int index)
    {
        return (bitField / (int)Math.Pow(10, index)) % 10;
    }

    public static bool GetFlag(int bitField, int index)
    {
        return GetBit(bitField, index) == 1;
    }
}

4
Kinh quá. Tại sao không chỉ sử dụng enums? Sử dụng ont nghìn để có nghĩa là 1-0-0-0 chỉ là vấn đề rắc rối.
Clément

1

Bạn có thể sử dụng 0b000001kể từ Visual Studio 2017 (C # 7.0)


0

Về cơ bản, tôi nghĩ câu trả lời là KHÔNG, không có cách nào dễ dàng. Sử dụng hằng số thập phân hoặc thập lục phân - chúng đơn giản và rõ ràng. Câu trả lời @RoyTinkers cũng tốt - sử dụng một nhận xét.

int someHexFlag = 0x010; // 000000010000
int someDecFlag = 8;     // 000000001000

Các câu trả lời khác ở đây trình bày một số công việc hữu ích - một vòng, nhưng tôi nghĩ chúng không tốt hơn câu trả lời đơn giản. Các nhà thiết kế ngôn ngữ C # có thể coi tiền tố '0b' là không cần thiết. HEX dễ dàng chuyển đổi thành nhị phân, và hầu hết các lập trình viên sẽ phải biết tương đương tháng 12 của 0-8.

Ngoài ra, khi kiểm tra các giá trị trong trình gỡ lỗi, chúng sẽ được hiển thị có HEX hoặc DEC.

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.