2010-03-09 14 views
5

¿Cuál es la mejor manera de definir en C# una estructura con, digamos, 6 bits de datos? Puedo, por supuesto, definir 2 campos de int + corto, pero me pregunto si hay una manera de mantener todos los datos en 1 archivados.Tipo de datos de tamaño de bit arbitrario en C#

+2

¿Puede especificar cómo va a utilizar estos datos. Además, no entiendo realmente tus matemáticas. Un 'int' es de 32bits y un corto es 16. Pero estás buscando 6bits. A menos que quisieras decir bytes. – kervin

+0

Necesito 6 bits, y exactamente 6 bits. Tengo colecciones de datos muy grandes. Mi objetivo es reducir la memoria consumiendo solo lo que necesito. –

Respuesta

4

BitVector32 fue diseñado teniendo en cuenta el empaquetado de bits (por supuesto, la estructura que desea almacenar tiene que caber en 32 bits).

Ver here y here para algunos ejemplos

+0

Necesito 6 bits, y exactamente 6 bits. Tengo colecciones de datos muy grandes. Mi objetivo es reducir la memoria consumiendo solo lo que necesito. –

+0

Tenía la impresión de que quería optimizar el almacenamiento para una estructura determinada. A la luz de su comentario, lo más parecido a sus requisitos es un BitArray pero ese BitArray está destinado a la lógica booleana y no a un sustituto de una estructura (aún puede hacerlo). Resolver las optimizaciones de espacio de memoria usando .net me parece muy poco natural, un lenguaje más cercano al sistema de operaciones (por ejemplo, C++) me parece más natural para este tipo de tareas. – Ando

2

Usted utiliza la clase BitArray para este propósito. Está en System.Collections

http://msdn.microsoft.com/en-us/library/system.collections.bitarray.aspx

+2

BitArray administra una matriz compacta de valores de bit, que se representan como Booleanos, donde verdadero indica que el bit está activado (1) y falso indica que el bit está desactivado (0) como dice MSDN, bool no es 1 bit en C# piense que BitArray no es una respuesta –

+0

Es probable que contenga bits en una matriz de entradas de 32 bits. Simplemente no puede asignar unos pocos bits de espacio en cualquier sistema moderno. – Patrick

+0

No estoy seguro de la cantidad de memoria que se necesita. Sé a veces que tengo que trabajar con hardware que toma un solo byte y usa los bits para representar varias opciones, aquí es donde uso BitArray ya que me permite configurar cada bit individualmente y luego copiar el resultado en un byte. – TimothyP

0

¿Usted intentó BitArray (System.Collections.BitArray)?

De lo contrario, no es arbitrario - int + short está limitado a .... 32 bits (longitud de int).

Para cualquier cosa más corta: toma la primitiva siguiente más larga y solo úsala.

0

Ok, usted debe haber significado 6 bytes de datos. Entonces su suma de matemáticas (int más corto es de 6 bytes).

Como han dicho otros, una colección sería lo mejor, pero parece que tienes que empacar todo en una estructura.

El tipo numérico más grande es el decimal y es 128 bits de ancho, mientras que una larga es 64. Puede utilizar los si realmente, realmente qué guardar los datos en la pila y contiguo (como lo que suena hacer).

+0

Mi matemática es incorrecta, mi error :) Necesito 6 bits, es decir, menos de un byte. Pero por el bien de la pregunta, puede ser cualquier otra cantidad de bits. –

2

Si te refieres a 6 bits, entonces un byte es suficiente para mantenerlos ya que tiene 8 bits.

public struct SixBits { 

    private byte _data; 

    private SixBits(byte value) { 
    _data = value; 
    } 

    public SixBits ChangeBit(int index, bool value) { 
    if (index < 0 || index > 5) throw new IndexOutOfRangeException(); 
    return new SixBits((byte)(_data & ~(1 << index) | ((value ? 1 : 0) << index))); 
    } 

    public bool this[int index] { 
    get { 
     if (index < 0 || index > 5) throw new IndexOutOfRangeException(); 
     return ((_data >> index) & 1) != 0; 
    } 
    } 

} 

Si se refiere a 6 bytes, un long es suficiente para mantenerlos ya que tiene 8 bytes.

public struct SixBytes { 

    private long _data; 

    private SixBytes(long value) { 
    _data = value; 
    } 

    public SixBytes ChangeByte(int index, byte value) { 
    if (index < 0 || index > 5) throw new IndexOutOfRangeException(); 
    return new SixBytes(_data & ~(0xFFL << (index * 8)) | (long)value << (index * 8)); 
    } 

    public byte this[int index] { 
    get { 
     if (index < 0 || index > 5) throw new IndexOutOfRangeException(); 
     return (byte)(_data >> (index * 8)); 
    } 
    } 

} 

Unidad de prueba de las estructuras anteriores:

SixBits x = new SixBits(); 
for (int i = 0; i < 6; i++) Assert.AreEqual(false, x[i]); 
for (int i = 0; i < 6; i++) x = x.ChangeBit(i, true); 
for (int i = 0; i < 6; i++) Assert.AreEqual(true, x[i]); 
for (int i = 0; i < 6; i++) x = x.ChangeBit(i, false); 
for (int i = 0; i < 6; i++) Assert.AreEqual(false, x[i]); 
for (int i = 0; i < 6; i++) x = x.ChangeBit(i, (i & 1) == 0); 
for (int i = 0; i < 6; i++) Assert.AreEqual((i & 1) == 0, x[i]); 
for (int i = 0; i < 6; i++) x = x.ChangeBit(i, (i & 1) == 1); 
for (int i = 0; i < 6; i++) Assert.AreEqual((i & 1) == 1, x[i]); 

SixBytes y = new SixBytes(); 
for (int i = 0; i < 256; i++) { 
    for (int j = 0; j < 6; j++) y = y.ChangeByte(j, (byte)i); 
    for (int j = 0; j < 6; j++) Assert.AreEqual((byte)i, y[j]); 
} 
byte[] test = { 0, 1, 64, 2, 255, 3, 14, 32, 4, 96, 6, 254, 7, 12, 255, 128, 127 }; 
for (int i = 0; i < test.Length - 6; i++) { 
    for (int j=0;j<6;j++) y = y.ChangeByte(j, test[i+j]); 
    for (int j=0;j<6;j++) Assert.AreEqual(test[i+j], y[j]); 
} 
Cuestiones relacionadas