// Конвертация массива бит в байт
public static class BitExt
{
public static byte ToByte(this BitArray bits)
{
byte result = 0;
for (byte index = 0, m = 1; index < 8; index++, m *= 2)
result += bits.Get(index) ? m : (byte)0;
return result;
}
}
// Собственно байт, битами которого оперируем
private byte _b = (byte)203; // 11001011
// Оболочка для работы с битами
public bool bit
{
get { return ((_b & 3) != 0); }
set
{
BitArray bits = new BitArray(_b);
bits[0] = value;
bits[1] = value;
_b = bits.ToByte();
}
}
[С#, VS2008] Ошибка при конвертации битового массива в байт
Есть байт. Есть флажок, повешенный на 1 и 2 биты. Нужно получить и изменить его значение. Вначале с true на false, затем обратно.
Я превращаю байт в массив битов. Изменяю нужные. Затем превращаю обратно в байт. С false все проходит. С true возникает проблема... Вот код:
Код:
Пытаюсь с этим работать:
Код:
bit; // => true
bit = false;
bit; // => false
bit = true; // вылетает с ошибкой
bit = false;
bit; // => false
bit = true; // вылетает с ошибкой
Отладчик матерится на метод:
public static byte ToByte(this BitArray bits)
Говорит, что index выходит за пределы диапазона. index в этот момент равен 7. А длина битового массива... тоже семи. И вот, собственно, вопрос: куда девается восьмой бит? :confused:
P.S. А, может. мой подход и вовсе в корне не верный и можно проще, лучше? Тогда подскажите - как? Все это безобразие творится внутри структуры и в C++ писалось не в пример проще, а тут я весь в сомнениях...
Флаги:
Код:
[Flags]
public enum DataBits : byte {
First = 1,
Second = 2
}
var x = DataBits.First | DataBits.Second;
Console.WriteLine((byte)x);
Console.WriteLine(x);
public enum DataBits : byte {
First = 1,
Second = 2
}
var x = DataBits.First | DataBits.Second;
Console.WriteLine((byte)x);
Console.WriteLine(x);
Побитовые операции:
Код:
byte x = 0;
x |= 1; // поднимаем первый бит
x |= 2; // поднимаем второй бит
x &= ~1; // сбрасываем первый бит
x &= ~2; // сбрасываем второй бит
x |= 1; // поднимаем первый бит
x |= 2; // поднимаем второй бит
x &= ~1; // сбрасываем первый бит
x &= ~2; // сбрасываем второй бит
Код:
char b;
b = 0; // => false
b = b | 1; // #0=false; #1=true
b = b | 2; // #0=true; #1=true
b = b & 2; // #0=false; #1=true
b = b ^ 1; // #0=true; #1=true
// и т.д.
b = 0; // => false
b = b | 1; // #0=false; #1=true
b = b | 2; // #0=true; #1=true
b = b & 2; // #0=false; #1=true
b = b ^ 1; // #0=true; #1=true
// и т.д.
p.s: hardcase синхронно :)
Хех. Всем устраивают. Большое спасибо! Действительно, переборщил. :)
x &= ~1;
x &= ~2;
Не проходит и гнусно матерится:
Постоянное значение "-2" не может быть преобразовано в "byte"
Он почему-то вместо инверсии бит делает число отрицательным...
---
Пробовал и так, в чистом виде. И написав функцию для работы с битами:
x |= (1 << i); // Установить бит i
x &= ~(1 << i); // Сбросить бит i
Результат один и тот же. Ставить ставит. А сбрасывать не хочет.
---
Руководствуясь нехитрой логикой, заменил "1" в сбросе на -1. Вроде бы, все заработало правильно. Теперь я буду бесконечно благодарен тому, кто объяснит мне - почему именно так, а не иначе, и с каких пор байт у нас стал знаковым. С отрицательными двоичными числами у меня вообще разговор особый, но хотелось бы понять что я только что сделал и к чему это приведет...
Цитата: EqKeeper
Хм....
x &= ~1;
x &= ~2;
Не проходит и гнусно матерится:
Постоянное значение "-2" не может быть преобразовано в "byte"
Он почему-то вместо инверсии бит делает число отрицательным...
x &= ~1;
x &= ~2;
Не проходит и гнусно матерится:
Постоянное значение "-2" не может быть преобразовано в "byte"
Он почему-то вместо инверсии бит делает число отрицательным...
Так сделайте его байтом :)
Код:
unchecked {
...
x &= (byte) ~2;
...
}
...
x &= (byte) ~2;
...
}
Большое спасибо. В байт я его пытался конвертнуть, но про блок unchecked не знал. За матчасть спасибо, наконец разобрался с отрицательными числами в бинарной системе. :)
Вопрос: а можно прикрутить к байту вышеозначенные формулы для работы с битами?
byte b = 4;
b.bits[0] = true; b.bits[1] = false;
Пробовал реализовать это при помощи методов расширения, но кроме вороха ошибок ничего толкового не добился. =\
А работать это должно примерно так:
Код:
class byte
public bool bits
{
get
{
if ((this & (1<<INDEX)) == 0) {return false;} else {return true;}
}
set
{
uncheced{
if (value) {this |= (1<<INDEX);} else {this &= (byte) ~(1<<INDEX);}
}
}
}
public bool bits
{
get
{
if ((this & (1<<INDEX)) == 0) {return false;} else {return true;}
}
set
{
uncheced{
if (value) {this |= (1<<INDEX);} else {this &= (byte) ~(1<<INDEX);}
}
}
}
Где INDEX - индекс в массиве бит.
Можно реализовать?
Цитата: EqKeeper
Все работает.
Вопрос: а можно прикрутить к байту вышеозначенные формулы для работы с битами?
Вопрос: а можно прикрутить к байту вышеозначенные формулы для работы с битами?
А зачем если есть формулы? Ну или на худой конец enum с флагами.
Цитата: hardcase
А зачем если есть формулы? Ну или на худой конец enum с флагами.
Код:
using System;
namespace flags
{
[Flags]
enum ByteFlags : byte {
Zero = 0,
All = 255,
b0 = 1,
b1 = 2,
b2 = 4,
b3 = 8,
b4 = 16,
b5 = 32,
b6 = 64,
b7 = 128,
}
class Program
{
private static void Print(ByteFlags flags) {
Console.WriteLine("Flags: {0}, Value: {1}", flags, (byte) flags);
}
public static void Main(string[] args)
{
var b = ByteFlags.Zero;
Print(b);
b |= ByteFlags.b2;
b |= ByteFlags.b5;
Print(b);
b ^= ByteFlags.All;
Print(b);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}
namespace flags
{
[Flags]
enum ByteFlags : byte {
Zero = 0,
All = 255,
b0 = 1,
b1 = 2,
b2 = 4,
b3 = 8,
b4 = 16,
b5 = 32,
b6 = 64,
b7 = 128,
}
class Program
{
private static void Print(ByteFlags flags) {
Console.WriteLine("Flags: {0}, Value: {1}", flags, (byte) flags);
}
public static void Main(string[] args)
{
var b = ByteFlags.Zero;
Print(b);
b |= ByteFlags.b2;
b |= ByteFlags.b5;
Print(b);
b ^= ByteFlags.All;
Print(b);
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
}
}
Еще раз большое спасибо! :)