C # ikili değişmez değerler


187

C # ile onaltılık 0x önek gibi ikili değişmezler yazmanın bir yolu var mı? 0b çalışmıyor.

Değilse, bunu yapmanın kolay yolu nedir? Bir tür dize dönüştürme?


2
Sabitleri kullanın ve onlara doğru isimler verin, o zaman bunları ondalık olarak yazmanız gerektiğinin önemi yoktur. Şahsen okumak isterdim if (a == MaskForModemIOEnabled)ziyadeif (a == 0b100101)
Lasse V. Karlsen

2
Başka bir not: Bu
gönderiyi

17
Dışında ikisi de çok iyi bir tavsiye, sınırlandırmakta bu adlandırılmış sabit tanımları ikili sabitin ile okuma ve yazma daha kolay olabilir dedi bitfields. [Bayraklar] enum Miktarı {Yok = 0, Bir = 1, Bazı = 0b10, En = 0b100, Tümü = 0b111}
brianary

1
Değeri ne olursa olsun , Roslyn için ikili değişmezlere destek planlanıyor .
Joe White

C # 6.0'da hala desteklenmiyor, değil mi? Vs2015'de ikili değişmezler kullanılamaz: /
anhoppe

Yanıtlar:


146

C # 7.0 , ikili değişmez değerleri (ve alt çizgi karakterleriyle isteğe bağlı basamak ayırıcıları) destekler.

Bir örnek:

int myValue = 0b0010_0110_0000_0011;

Roslyn GitHub sayfasında daha fazla bilgi bulabilirsiniz .


3
@ D.Singh Şimdi C # 7 listesinde görüyorum. github.com/dotnet/roslyn/issues/2136
Danation

9
Tatlı! VS2017 / C # 7'de harika çalışıyor.
STLDev

1
C # 'ın İkili Değişmezlerinin büyük endian olduğunu, ancak x86 tamsayılarının küçük endian olduğunu hatırlamaya yardımcı olur, bu nedenle - kafa karıştırıcı Int16 = 0b0010_0110_0000_0011olarak saklanacaktır { 0b0000_0011, 0b0010_0110 }.
Dai

1
@ Dai, onaltılı değişimlerden farklı değil. Başka bir deyişle, tüm sabitler büyük endian, ancak Intel / AMD ve çoğu ARM'de küçük endian depoladı. 0xDEADBEEF0xEF 0xBE 0xAD 0xDE
Cole Johnson

170

Güncelleme

C # 7.0 şimdi müthiş ikili değişmez var.

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

Orijinal Mesaj

Konu, numaralandırmalarda bit tabanlı bayrak değerlerini bildirmeye dönüştüğü için, bu tür şeyler için kullanışlı bir numaraya işaret etmeye değeceğini düşündüm. Sola kaydırma operatörü ( <<), belirli bir ikili konuma biraz itmenizi sağlar. Bunu, aynı sınıftaki diğer değerler açısından enum değerleri bildirme özelliğiyle birleştirin ve bit bayrağı numaralandırmaları için okunması çok kolay bir bildirim sözdizimine sahip olun.

[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: Birçok geliştirici bunu tercih ediyor. Kafamdaki hex'i bazı geliştiriciler gibi dönüştürmede iyi değilim ve bazen en düşük ortak paydaya hitap etmek en iyisidir.
StriplingWarrior

2
Bence bu en etkili yol çünkü enumlar sabit olarak inşa ediliyor. İsteğe bağlı [Bayraklar] özelliğiyle, bitsel işlemlerde kullanılabilirler (doğrudan soru ile ilgili değildir, ancak özellikle ikili değişmezleri tanımlarken yararlıdır). Bir başka ilginç olasılık, enum türünü yerleşik bir tür olarak zorlamaktır (bu örnekte, 'Günler'den sonra': byte 'ekleyin); bit.ly/MKv42E'de
caligari

Bir
Enum'a

5
@MikeT: Bu son düşünceyi ayrıntılı bir şekilde açıklayabilir (veya ayrıntılı bir bağlantı sağlayabilir misiniz?) Sıklıkla "1" ile başlayan numaralandırmalar bildiririm çünkü bir değer hiç başlatılmadığında hızlı bir şekilde tespit edip başarısız olmak istiyorum . Ancak, varsayılan bir değerin gerçekten mantıklı olduğu bazı durumlar vardır ve bu değer için bir ad eklemenin yanlış bir şey olmayacağını düşünürüm.
StriplingWarrior

3
@MikeT ca1008'den : " FlagsAttribute uygulanmış bir numaralandırma sıfır değerli bir üye tanımlarsa, numaralandırmada hiçbir değerin ayarlanmadığını belirtmek için adı" Yok "olmalıdır." Mükemmel geçerli olduğundan Yani, varsayılan değer olarak hizmet eklemek eğer o "Yok" denir. Genel olarak, varsayılan olarak başlatılmış bir alandaki değerin gerçekten gösterilecek bir adı varsa bana daha temiz görünüyor.
Nyerguds

115

Sadece tamsayı ve onaltılık doğrudan, korkarım (ECMA 334v4):

9.4.4.2 Tamsayı değişmez değerleri Tamsayı değişmez değerleri, int, uint, long ve ulong türlerinin değerlerini yazmak için kullanılır. Tamsayı değişmez değerleri iki olası forma sahiptir: ondalık ve onaltılık.

Ayrıştırmak için şunları kullanabilirsiniz:

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

4
Bu cevaba bir güncelleme olarak, en son modern bilgilerle (Temmuz 2014); C # 6.0 ikili değişmezleri tanıtır. Güncellenmiş cevabımı aşağıdan aşağıya bakın ...
BTownTKD

1
@BTownTKD cevabınız aslında en üstte :) kabul edilen cevap olduğu için.
RBT

25

@ StriplingWarrior'ın numaralardaki bit bayrakları hakkındaki cevabına ek olarak, bit kaydırmalarında yukarı doğru saymak için onaltılık olarak kullanabileceğiniz kolay bir kural var. 1-2-4-8 dizisini kullanın, bir sütunu sola hareket ettirin ve tekrarlayın.

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

Sağ sütundan başlayarak aşağı doğru tarayın ve 1-2-4-8 (shift) 1-2-4-8 (shift) desenine dikkat edin ...


Orijinal soruyu cevaplamak için, @ Sahuagin'in onaltılı değişmezleri kullanma önerisini ikinci olarak verdim. Bunun bir endişe olabilmesi için genellikle ikili sayılarla çalışıyorsanız, onaltılık asmak için zaman ayırmaya değer.

Kaynak kodda ikili sayıları görmeniz gerekiyorsa, yukarıdaki gibi ikili değişmez değerleri olan yorumları eklemenizi öneririm.


23

İstediğiniz değeri içeren sabitler, sabitler her zaman oluşturabilirsiniz:

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

Bunları sık sık kullanırsanız, yeniden kullanmak üzere statik bir sınıfa alabilirsiniz.

Ancak, hafif bir konu dışı, (derleme zamanında bilinen) bit ile ilişkili herhangi bir anlambiliminiz varsa bunun yerine bir Enum kullanmanızı öneririm:

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


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

Bunu kullanarak, 8bit ikili için, bunu statik bir sınıf yapmak için kullanıyorum ve panoya koyar .. Sonra projeye yapıştırılır ve Kullanma bölümüne eklenir, böylece nb001010 ile her şey bir tablodan alınır, en az statik, ama yine de ... Ben çok PIC grafik kodlama için C # kullanın ve Hi-Tech C 0b101010 çok kullanın

- kod çıkışından örnek--

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

İkili hazır bilgi özelliği C # 6.0 ve Visual Studio 2015'te uygulanmadı. Ancak 30 Mart 2016'da Microsoft, Visual Studio '15' Önizleme'nin yeni sürümünü ikili değişmezleri kullanabileceğimizi duyurdu.

Rakam ayırıcılar için bir veya daha fazla Alt Çizgi (_) karakteri kullanabiliriz. kod pasajı şöyle görünecektir:

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

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

ve yukarıdaki kod snippet'inde gösterildiği gibi 0b ve 0B'den birini kullanabiliriz.

basamak ayırıcı kullanmak istemiyorsanız, aşağıdaki kod snippet'i gibi basamak ayırıcı olmadan kullanabilirsiniz

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

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

2

Değişmez kullanmak mümkün olmasa da, belki bir BitConverter de bir çözüm olabilir?


BitConverter, makine-endian olduğu için biraz zorlaşıyor; ve standart Intel'inizde bu küçük endian anlamına gelir. Çoğu insan küçük endian değişmezlerini okumakta zorluk çeker ...
Marc Gravell

1
Ah, şimdi neden hep farkında olduğumu hatırlıyorum ama hiç BitConverter kullanmadım ...
Michael Stum

4
BitConverter, BitConverter.IsLittleEndianana makine küçük endian değilse test etmek (ve bir arabelleği ters çevirmek) için kullanabileceğiniz alana sahiptir .
foxy

1

Dize ayrıştırma çözümü en popüler olsa da, sevmiyorum, çünkü dize ayrıştırma bazı durumlarda büyük bir performans hit olabilir.

Bir tür bitfield veya ikili maske gerektiğinde, şöyle yazmayı tercih ederim

uzun bitMask = 1011001;

Ve sonra

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

Veya

bool flag5 = BitField.GetFlag (bitMask, 5); `

BitField sınıfı nerede

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. Neden sadece numaralandırmalar kullanılmıyor? 1-0-0-0 demek için on bin kullanmak sadece sorun istiyor.
Clément

1

0b000001Visual Studio 2017'den beri kullanabilirsiniz (C # 7.0)


0

Temel olarak, cevabın HAYIR olduğunu düşünüyorum, kolay bir yolu yok. Ondalık veya onaltılık sabitleri kullanın - basit ve anlaşılır. @RoyTinkers yanıtı da iyi - bir yorum kullanın.

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

Buradaki diğer cevaplar birkaç yararlı çalışma turu sunuyor, ancak bence basit cevaptan daha iyi değiller. C # dil tasarımcıları muhtemelen '0b' önekini gereksiz bulmuşlardır. HEX'in ikiliye dönüştürülmesi kolaydır ve çoğu programcı zaten 0-8'in DEC eşdeğerlerini bilmek zorunda kalacaktır.

Ayrıca, hata ayıklayıcıdaki değerleri incelerken, bunlar HEX veya DEC olarak görüntülenir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.