Вопрос

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

Есть ли способ превратить int «4096» в 3 байта?или «1053» в 2 байта?

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

Это было полезно?

Решение

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

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

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

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

Другие советы

Просто для безумия давайте сделаем это в 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, поэтому не знаю, дешевле ли это по сравнению с любым другим решением.

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

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

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 байта и т. д.

Более сложные способы сделать это можно найти на этой странице

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

и

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top