C # 3 байта Ints - PullRequest
       19

C # 3 байта Ints

4 голосов
/ 15 января 2009

Я работаю над проектом, где мне нужно иметь дело с байтами на целых числах. Так как экономия места является основным фактором, мне нужны только очень маленькие (и переменные длины).

Есть ли способ, которым я могу превратить int '4096' в 3 байта? или «1053» в 2 байта?

Очевидно, я не могу сделать это вручную = (byte [0] * 256) + (byte [1]), но мне было интересно, есть ли более простой вариант для преобразования int в x байтов и обратно?

Ответы [ 5 ]

14 голосов
/ 15 января 2009

Можешь? Конечно. Это сэкономит место? Возможно, в зависимости от того, сколько работы вы хотите сделать. Вы должны понимать, что процессор 32-битный, то есть он имеет 4-байтовые регистры, поэтому он хочет хранить и получать доступ к вещам. Для принудительного использования 3-байтового «int» вам придется хранить его в байтовом массиве и извлекать его из массива по выровненному адресу перед использованием. Это означает, что если вы сохраните его коротким, компилятор либо дополнит его (и вы потеряете всю эффективность, которую, по вашему мнению, вы создали), либо он будет на много медленнее читать и писать. 1003 *

Если это приложение для настольного компьютера, как именно экономит место в первую очередь, особенно когда речь идет об 1 байте на элемент? Наказание за доступ к элементу может изменить ваше мнение о том, насколько важен этот байт.

Я бы сказал, что если этот 1 байт действительно важен, то, может быть, просто, может быть, вы все равно используете неправильный язык. Количество байтов, которые вы сохраните, если я не установлю и не буду использовать CLR, составляет лот из этих байтов.

Примечание: вы бы также сделали сдвиг, а не умножение (хотя компилятор, скорее всего, доберется до вас).

5 голосов
/ 15 января 2009

Только для дополнительного безумия, давайте сделаем это в C #, используя старый трюк объединения в стиле C:

[StructLayout(LayoutKind.Explicit)]
struct OddUnion
{
    /* The 32-bit integer value */
    [FieldOffset(0)]
    public int IntegerValue;

    /* The bytes that overlap with it */
    [FieldOffset(0)]
    public byte Byte1;
    [FieldOffset(1)]
    public byte Byte2;
    [FieldOffset(2)]
    public byte Byte3;
    [FieldOffset(3)]
    public byte Byte4;
 }

И затем, когда вы хотите «конвертировать», сделайте следующее:

OddUnion myOddUnion;
myOddUnion.IntegerValue = 4096;
Byte secondByte = myOddUnion.Byte1;

Но это действительно помогает только в том случае, если вы хотите «сэкономить» на стоимости сдвига битов в одном байте слова. Я не смотрел на сгенерированный SMIL, поэтому не знаю, дешевле ли это по сравнению с любым другим решением.

5 голосов
/ 15 января 2009

Вы можете сделать целочисленное кодирование переменной длины. Старый метод много лет назад состоял в том, чтобы использовать старший бит каждого байта для обозначения того, что целое число продолжается до другого байта. Таким образом, вы теряете один бит на байт, но получаете маленькие целые числа. Это в основном полезно в постоянном хранилище, где учитывается каждый последний байт.

Пример: Предположим, что мы имеем дело с целыми числами без знака, у нас будет

int  binary
0                       00000000
1                       00000001
...  
127                     01111111
128            00000001 10000000
129            00000001 10000001
...
255            00000001 11111111
256            00000010 10000000
...
16383          01111111 11111111
16384 00000001 10000000 10000000 

, поэтому 0-127 занимает 1 байт, а 128-16383 занимает 2 байта и т. Д ...

Для более сложных способов сделать это проверьте эту страницу

3 голосов
/ 15 января 2009

BitConverter.GetBytes даст вам байты.

и

BitConverter.ToInt32 получит 32-битное int из байтов.

1 голос
/ 15 января 2009

Вы должны сделать немного сдвига. Гораздо проще, если вы работаете с HEX, поскольку каждое число (я имею в виду каждую цифру, но цифра для основы 10, hexgit) представляет четыре бита.

...