2010-03-09 5 views
5

Quelle est la meilleure façon de définir en C# une structure avec, disons, 6 bits de données? Je peux, bien sûr, définir 2 champs de int + short, mais je me demande s'il existe un moyen de conserver toutes les données dans 1 classées.Type de données de taille de bit arbitraire en C#

+2

Pouvez-vous indiquer comment vous utiliserez ces données. Plus pas vraiment comprendre vos maths. Un 'int' est 32bits et un short est 16. Mais vous cherchez 6bits. Sauf si vous voulez dire des octets. – kervin

+0

J'ai besoin de 6 bits, et exactement 6 bits. J'ai de très grandes collections de données. Mon but est de réduire la mémoire en ne consommant que ce dont j'ai besoin. –

Répondre

4

BitVector32 a été conçu en tenant compte de l'emboutissage (bien sûr, la structure que vous voulez stocker doit tenir sur 32 bits).

Voir here et here quelques exemples

+0

J'ai besoin de 6 bits, et exactement 6 bits. J'ai de très grandes collections de données. Mon but est de réduire la mémoire en ne consommant que ce dont j'ai besoin. –

+0

J'avais l'impression que vous vouliez optimiser le stockage pour une certaine structure. À la lumière de votre commentaire, la chose la plus proche de vos besoins est un BitArray mais que BitArray est destiné à la logique booléenne et non pas à une structure de remplacement (vous pouvez toujours le faire). Résoudre des problèmes d'optimisation de l'espace mémoire en utilisant .net me semble très anormal, un langage plus proche du système d'exploitation (par exemple C++) me semblerait plus naturel pour ce genre de tâches. – Ando

2

Vous utilisez la classe BitArray à cette fin. Il est dans System.Collections

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

+2

BitArray gère une matrice compacte de valeurs binaires, qui sont représentées comme Booleans, où true indique que le bit est activé (1) et false indique que le bit est désactivé (0) comme MSDN dit, bool n'est pas 1 bit dans C# pense que BitArray n'est pas une réponse –

+0

Il est probable qu'il se transforme en bits en un tableau de 32 bits. Vous ne pouvez pas allouer quelques bits d'espace dans un système moderne. – Patrick

+0

Je ne suis pas sûr de la quantité de mémoire nécessaire. Je sais parfois que je dois travailler avec du matériel qui prend un seul octet et utilise les bits pour représenter diverses options, c'est là que j'utilise le BitArray car cela me permet de définir chaque bit individuellement et de copier le résultat dans un octet. – TimothyP

0

Avez-vous essayé BitArray (System.Collections.BitArray)?

Sinon, vous n'êtes pas arbitraire - int + court est limité à .... 32 bits (longueur de int).

Pour tout ce qui est plus court - prenez la primitive suivante la plus longue et utilisez-la.

0

Ok, vous devez avoir signifié 6 octets de données. Ensuite, vos maths s'additionnent (int plus court est de 6 octets).

Comme d'autres l'ont dit, une collection serait la meilleure, mais il semble que vous deviez tout emballer dans une structure.

Le plus grand type numérique est la décimale et il est 128bits large, tandis qu'un temps est 64. Vous pouvez les utiliser si vous vraiment, vraiment ce qu'il faut garder que les données sur la pile et contigu (comme il vous sons faire).

+0

Mes maths sont faux, mon erreur :) J'ai besoin de 6 bits, c'est-à-dire moins d'un octet. Mais pour l'amour de la question, peut être n'importe quel autre nombre de bits. –

2

Si vous voulez dire 6 bits, alors un byte est suffisant pour les contenir car il a 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 vous voulez dire 6 octets, un long est suffisant pour les maintenir comme il l'a 8 octets.

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

} 

test unitaire pour les structures ci-dessus:

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]); 
} 
Questions connexes