C # ตัวอักษรไบนารี


187

มีวิธีเขียนตัวอักษรไบนารีใน C # เช่นเลขฐานสิบหกนำหน้าด้วย 0x หรือไม่ 0b ไม่ทำงาน

ถ้าไม่ใช่วิธีง่าย ๆ ที่จะทำคืออะไร? การแปลงสตริงบางชนิด?


2
ใช้ค่าคงที่และตั้งชื่อให้ถูกต้องจากนั้นความจริงที่ว่าคุณต้องเขียนมันเป็นทศนิยมไม่ควรสำคัญ โดยส่วนตัวฉันต้องการอ่านif (a == MaskForModemIOEnabled)มากกว่าif (a == 0b100101)
Lasse V. Karlsen

2
หมายเหตุอื่น: หากคุณพบโพสต์นี้เนื่องจากคุณต้องการฟิลด์บิตโปรดพิจารณา flag-attribute: msdn.microsoft.com/en-us/library/cc138362.aspx#sectionToggle0
toxvaerd

17
ทั้งคำแนะนำที่ดีมากยกเว้นเมื่อกำหนด bitfields ดังกล่าวซึ่งคำจำกัดความคงที่ที่มีชื่อเหล่านี้สามารถอ่านและเขียนด้วยตัวอักษรไบนารีได้ง่ายขึ้น [ค่าสถานะ] จำนวน enum {ไม่มี = 0, หนึ่ง = 1, บางส่วน = 0b10, มากที่สุด = 0b100, ทั้งหมด = 0b111}
ปกครอง

1
สำหรับสิ่งที่คุ้มค่าการสนับสนุนสำหรับตัวอักษรไบนารีมีการวางแผนสำหรับโรสลิน
Joe White

ยังไม่รองรับใน C # 6.0 ใช่ไหม ไม่สามารถใช้ตัวอักษรไบนารีใน vs2015: /
anhoppe

คำตอบ:


146

C # 7.0รองรับตัวอักษรไบนารี (และตัวคั่นตัวเลขที่เป็นตัวเลือกผ่านตัวอักษรขีดล่าง)

ตัวอย่าง:

int myValue = 0b0010_0110_0000_0011;

นอกจากนี้คุณยังสามารถค้นหาข้อมูลเพิ่มเติมเกี่ยวกับหน้าโรสลิน GitHub


3
@ D.Singh ฉันเห็นมันในรายการ C # 7 ตอนนี้ github.com/dotnet/roslyn/issues/2136
Danation

9
หวาน! ทำงานได้ดีใน VS2017 / C # 7
STLDev

1
มันจะช่วยให้จำได้ว่าตัวอักษรไบนารีของ C # นั้นเป็นตัวอักษรตัวใหญ่ แต่ในจำนวนเต็ม x86 นั้นเป็นตัวเล็กตัวน้อยดังนั้นInt16 = 0b0010_0110_0000_0011จะถูกเก็บไว้เป็น{ 0b0000_0011, 0b0010_0110 }- ทำให้สับสน
Dai

1
@ ไดที่ไม่แตกต่างจากตัวอักษรฐานสิบหก กล่าวอีกนัยหนึ่งค่าคงที่ทั้งหมดคือ endian ใหญ่ แต่เก็บไว้ endian เล็กน้อยบน Intel / AMD และ ARM ส่วนใหญ่ 0xDEADBEEFจะถูกเก็บเป็น0xEF 0xBE 0xAD 0xDE
โคลจอห์นสัน

170

ปรับปรุง

ตอนนี้ C # 7.0 มีตัวอักษรไบนารีซึ่งยอดเยี่ยมมาก

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

โพสต์ต้นฉบับ

เนื่องจากหัวข้อดูเหมือนจะเปลี่ยนเป็นการประกาศค่าสถานะบิตตาม enums ฉันคิดว่ามันจะคุ้มค่าชี้เคล็ดลับสะดวกสำหรับสิ่งนี้ ผู้ประกอบการกะซ้าย ( <<) จะช่วยให้คุณสามารถผลักดันบิตไปยังตำแหน่งไบนารีที่เฉพาะเจาะจง รวมที่มีความสามารถในการประกาศค่า enum ในแง่ของค่าอื่น ๆ ในชั้นเรียนเดียวกันและคุณมีไวยากรณ์ประกาศง่ายต่อการอ่านมากสำหรับบิตธง enums

[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: นักพัฒนาหลายคนชอบสิ่งนั้น ฉันไม่ดีเท่าการแปลงเลขฐานสิบหกในหัวของฉันเหมือนที่นักพัฒนาบางคนเป็นและบางครั้งก็เป็นการดีที่สุดที่จะตอบสนองต่อตัวหารร่วมที่ต่ำที่สุด
StriplingWarrior

2
ฉันคิดว่านี่เป็นวิธีที่มีประสิทธิภาพที่สุดตั้งแต่สร้าง enums เป็นค่าคงที่ ด้วยแอตทริบิวต์ [Flags] ซึ่งเป็นตัวเลือกสามารถใช้ในการดำเนินการระดับบิต (ไม่เกี่ยวข้องโดยตรงกับคำถาม แต่มีประโยชน์อย่างยิ่งเมื่ออธิบายไบนารีตัวอักษร) ความเป็นไปได้ที่น่าสนใจอีกอย่างหนึ่งคือการบังคับให้ enum เป็นชนิดบิวด์อิน (ในตัวอย่างนี้เพิ่ม ': byte' หลังจาก 'Days'); ดูประเภทในตัวในbit.ly/MKv42E
caligari

ที่จริงแล้วเป็นเรื่องง่ายมากที่จะอ่านแม้ว่าการประกาศค่าสถานะ 0 บน Enum นั้นเป็นวิธีปฏิบัติที่ไม่ดีเลยทีเดียว
MikeT

5
@MikeT: คุณสามารถทำอย่างละเอียด (หรือให้ลิงค์ที่อธิบายเพิ่มเติม) ในความคิดครั้งสุดท้ายได้หรือไม่? ฉันมักจะประกาศ enums ที่เริ่มต้นด้วย "1" เพราะฉันต้องการที่จะสามารถตรวจจับและล้มเหลวอย่างรวดเร็วเมื่อค่าไม่เคยเริ่มต้น แต่มีบางสถานการณ์ที่ค่าเริ่มต้นสมเหตุสมผลและฉันคิดว่าคงไม่มีอะไรผิดปกติในการเพิ่มชื่อสำหรับค่านั้น
StriplingWarrior

3
@MikeT จากca1008 : "หากการแจงนับที่มีการใช้ FlagsAttribute จะกำหนดสมาชิกที่มีค่าเป็นศูนย์ชื่อของมันควรเป็น 'ไม่มี' เพื่อระบุว่าไม่มีการตั้งค่าใด ๆ ในการแจงนับ" ดังนั้นจึงเป็นสิ่งที่ถูกต้องสมบูรณ์ในการเพิ่มเพื่อใช้เป็นค่าเริ่มต้นหากเรียกว่า "ไม่มี" โดยรวมแล้วดูเหมือนว่าจะสะอาดกว่าสำหรับฉันถ้าค่าในเขตข้อมูลที่กำหนดค่าเริ่มต้นจริงมีชื่อที่จะแสดง
Nyerguds

115

เฉพาะจำนวนเต็มและฐานสิบหกโดยตรงฉันกลัว (ECMA 334v4):

9.4.4.2 ตัวอักษรจำนวนเต็มตัวอักษรตัวเต็มใช้เพื่อเขียนค่าของชนิด int, uint, long และ ulong ตัวอักษรจำนวนเต็มมีสองรูปแบบที่เป็นไปได้: ทศนิยมและเลขฐานสิบหก

ในการแยกวิเคราะห์คุณสามารถใช้:

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

4
เป็นการอัปเดตคำตอบนี้พร้อมข้อมูลล่าสุดที่ทันสมัย ​​(กรกฎาคม 2014) C # 6.0 แนะนำตัวอักษรไบนารี ดูคำตอบที่อัปเดตของฉัน wayyyyyy ที่ด้านล่าง ...
BTownTKD

1
@ BTTTDD คำตอบของคุณคือด้านบนสุด :) เนื่องจากเป็นคำตอบที่ยอมรับได้
RBT

25

การเพิ่มคำตอบของ @ StriplingWarrior เกี่ยวกับการตั้งค่าสถานะบิตใน enums มีวิธีการง่ายๆที่คุณสามารถใช้เป็นเลขฐานสิบหกเพื่อนับจำนวนขึ้นไปจนถึงการเลื่อนบิต ใช้ลำดับ 1-2-4-8 ย้ายหนึ่งคอลัมน์ไปทางซ้ายและทำซ้ำ

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

สแกนเริ่มต้นด้วยคอลัมน์ด้านขวาและสังเกตรูปแบบ 1-2-4-8 (shift) 1-2-4-8 (shift) ...


เพื่อตอบคำถามเดิมฉันขอแนะนำ @ Sahuagin ให้ใช้ตัวอักษรฐานสิบหก หากคุณกำลังทำงานกับเลขฐานสองบ่อยครั้งพอที่จะเป็นข้อกังวลคุณควรใช้เวลาสักพักเพื่อให้ได้เลขฐานสิบหก

หากคุณต้องการดูเลขฐานสองในซอร์สโค้ดฉันขอแนะนำให้เพิ่มความคิดเห็นด้วยตัวอักษรไบนารีเหมือนที่ฉันมีด้านบน


23

คุณสามารถสร้างตัวอักษรเสมือนค่าคงที่ซึ่งมีค่าที่คุณอยู่หลัง:

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

หากคุณใช้บ่อยๆคุณสามารถห่อมันไว้ในคลาสแบบคงที่เพื่อนำมาใช้ซ้ำ

อย่างไรก็ตามเล็กน้อยนอกหัวข้อถ้าคุณมีความหมายใด ๆ ที่เกี่ยวข้องกับบิต (รู้จักกันในเวลารวบรวม) ฉันขอแนะนำให้ใช้ Enum แทน:

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

18

หากคุณดูที่สถานะการใช้งานคุณสมบัติภาษาของ. NET Compiler Platform ("Roslyn") คุณสามารถเห็นได้อย่างชัดเจนว่าใน C # 6.0 นี่เป็นคุณสมบัติที่วางแผนไว้ดังนั้นในรุ่นถัดไปเราสามารถทำได้ตามปกติ

สถานะตัวอักษรไบนารี


3
มันเกิดขึ้นจริงหรือ คุณสมบัติบางอย่างที่ไม่ได้ถูก blogged เกี่ยวกับการทำจริงปล่อย Visual Studio 2015
พันเอก Panic

4
@ColonelPanic - Danationชี้ให้เห็นว่ามันเป็น "ในรายการ C # 7 ตอนนี้" - github.com/dotnet/roslyn/issues/2136
Wai Ha 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);

ใช้สิ่งนี้สำหรับไบนารี 8 บิตฉันใช้สิ่งนี้เพื่อสร้างคลาสแบบคงที่และใส่ลงในคลิปบอร์ด .. จากนั้นมันจะถูกวางลงในโครงการและเพิ่มลงในส่วนการใช้ดังนั้นทุกอย่างที่มี nb001010 จะถูกนำออกจากตารางที่ คงน้อยที่สุด แต่ก็ยัง ... ฉันใช้ C # สำหรับการเข้ารหัสกราฟิก PIC จำนวนมากและใช้ 0b101010 จำนวนมากใน Hi-Tech C

- ตัวอย่างจากโค้ด 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, 
}

:-) NEAL


3

คุณลักษณะตัวอักษรแบบไบนารีไม่ถูกนำมาใช้ใน C # 6.0 และ Visual Studio 2015 แต่ในวันที่ 30 มีนาคม 2559 Microsoft ประกาศรุ่นใหม่ของ Visual Studio '15' แสดงตัวอย่างพร้อมที่เราสามารถใช้ตัวอักษรไบนารี

เราสามารถใช้อักขระขีดล่าง (_) หนึ่งตัวหรือมากกว่าสำหรับตัวคั่นหลัก ดังนั้นข้อมูลโค้ดจะมีลักษณะดังนี้:

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

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

และเราสามารถใช้อย่างใดอย่างหนึ่งของ 0b และ 0B ตามที่แสดงในตัวอย่างโค้ดข้างต้น

หากคุณไม่ต้องการใช้ตัวคั่นหลักคุณสามารถใช้มันได้โดยไม่ต้องมีตัวคั่นหลักเช่นโค้ดด้านล่าง

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

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

2

ในขณะที่ไม่สามารถใช้ตัวอักษรได้BitConverterอาจเป็นวิธีแก้ปัญหาได้เช่นกัน


BitConverter ทำให้ยุ่งยากเล็กน้อยเพราะเป็นเครื่อง endian; และใน Intel แบบมาตรฐานของคุณนั่นหมายถึงผู้ที่มีความเอนเอียงเล็กน้อย คนส่วนใหญ่มีความยากลำบากในการอ่านตัวอักษรน้อย endian ...
Marc Gravell

1
โอ๊ยตอนนี้ผมจำได้ว่าทำไมผมก็มักจะตระหนักถึง แต่ไม่เคยใช้ BitConverter ...
ไมเคิล Stum

4
BitConverter มีฟิลด์BitConverter.IsLittleEndianซึ่งคุณสามารถใช้ทดสอบ (และย้อนกลับบัฟเฟอร์) หากเครื่องโฮสต์ไม่ได้เป็น endian น้อย
เจ้าเล่ห์

1

แม้ว่าวิธีการแยกวิเคราะห์สตริงเป็นที่นิยมที่สุด แต่ฉันไม่ชอบเพราะการแยกสตริงสามารถประสิทธิภาพที่ยอดเยี่ยมในบางสถานการณ์

เมื่อมีความจำเป็นต้องใช้ bitfield หรือหน้ากากชนิดหนึ่งฉันควรจะเขียนแบบนี้

ยาว bitMask = 1011001;

และหลังจากนั้น

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

หรือ

บูล flag5 = BitField.GetFlag (bitMask, 5); `

คลาส BitField อยู่ที่ไหน

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
yuck ทำไมไม่ใช้ enums ล่ะ? การใช้ออนโทพันเพื่อหมายถึง 1-0-0-0 เป็นเพียงการถามหาปัญหา
Clément


0

โดยพื้นฐานแล้วฉันคิดว่าคำตอบคือไม่ไม่มีวิธีง่ายๆ ใช้ค่าคงที่ทศนิยมหรือฐานสิบหก - พวกเขาจะง่ายและชัดเจน @RoyTinkers คำตอบก็ดีเช่นกัน - ใช้ความคิดเห็น

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

คำตอบอื่น ๆ ที่นี่นำเสนอรอบการทำงานที่มีประโยชน์หลายอย่าง แต่ฉันคิดว่าพวกเขาอาจจะไม่ได้คำตอบง่ายๆ ผู้ออกแบบภาษา C # อาจถือว่าคำนำหน้า '0b' ไม่จำเป็น HEX นั้นง่ายต่อการแปลงเป็นไบนารี่และโปรแกรมเมอร์ส่วนใหญ่จะต้องรู้ค่า DEC ของ 0-8 ต่อไป

นอกจากนี้เมื่อตรวจสอบค่าในดีบักเกอร์ค่าเหล่านั้นจะแสดงเป็น HEX หรือ DEC

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.