Преобразование байтов в массив символов - и обратно - PullRequest
1 голос
/ 17 января 2012

Я нахожусь в процессе создания программы, которая извлекает двоичные / байтовые данные двойного числа и преобразует их в шестнадцатеричное. Затем необходимо применить обратное: преобразовать шестнадцатеричный код обратно в байты, чтобы его снова можно было использовать как двойное число.

Это то, что я исследую для проекта. Идея заключается в том, что «некоторая точность может быть потеряна при сохранении двойных значений в форме ASCII, а не при сохранении байтового значения», - считает мой руководитель. Эти значения должны быть сохранены и прочитаны тысячи раз, поэтому важна точность исходного двойного значения.

Лично я не вижу проблемы. Например, у меня есть следующий код, который извлекает байты двойного из памяти и преобразует его в шестнадцатеричное.

string double_to_hex_string(double d)
{
    unsigned char *buffer = (unsigned char*)&d;

    int bufferSize = sizeof(double);

    char converted[bufferSize *2];

    int j = 0;
    for(int i = bufferSize - 1; i >= 0 ; --i)
    {
        sprintf(&converted[j*2], "%02X", buffer[i]);
        ++j;
    }

    string hex_string(converted);
    return hex_string;
}

Двойное значение 0,61 представляется в памяти как 0,60999 (повторное возникновение). Однако оба значения дают одинаковое шестнадцатеричное значение, поскольку эти числа одинаковы и могут быть представлены только одним способом. Я так думаю, но мне все равно велено расследовать.

Мой главный вопрос заключается в преобразовании между типами - особенно обратно из шестнадцатеричной строки в двойное значение. Я использую много кода вне Интернета, не понимая, как представлены байты. Мое текущее понимание:

  • Числа типа double (или любого другого типа) хранятся в памяти и являются значениями в диапазоне от 0 до 255. Таким образом, символы без знака являются разумным способом хранения этих байтовых значений (один байт).

  • Эти значения символов являются просто 8-битными целыми числами. И может быть легко преобразован в шестнадцатеричное.

Чтобы преобразовать обратно, я предполагаю следующие шаги (как раз наоборот):

  • Преобразовать каждую пару шестнадцатеричных значений в строке в беззнаковый символ.

  • Соберите эти символы в массив.

  • Привести массив символов обратно к удвоению (каким-либо образом).

Буду признателен за любые указания, касающиеся этого, особенно за все, что я могу упустить из виду в своем обращении, и за любые исправления в заявлениях, которые я сделал в приведенном выше тексте.

1 Ответ

2 голосов
/ 18 января 2012

ОК, некоторые ответы.Предположим, ради аргумента, что это наиболее распространенное определение double, а именно 64-битный стандарт IEE 754.

Благодаря тому, как эти вещи работают, можно выразить значениепеременной двойной точности точно в десятичной.Например, вы можете хранить 2 ^ 200 в одном, и вы сможете записать это точно в виде десятичного числа с 61 цифрой.Никто никогда не делает этого, но, поверьте мне, это возможно.

Когда ухудшение наступает, когда вы пытаетесь хранить вещи в двойном формате, который не может быть выражен точно в его формате, например 1/7.Ближайшим приближением является число, начинающееся с 16 правильных цифр после десятичной точки, но если вы считаете, что остальные цифры не имеют значения, вы ошибаетесь.Запись в файл только этих 16 цифр (т. Е. Число .1428571428571428) и последующее чтение его приведут к немного другому значению, чем у вас было раньше, что отличается от 1/7.

Так что да, если вы должны записать номер в файл и прочитать его обратно, не делайте так.Если вы не можете просто записать «родной» байтовый контент в двоичный файл, допустимым вариантом является использование 16 шестнадцатеричных цифр.
Вот, пожалуйста.Если мы снова предположим, что double равен 8 байтам, вам не понадобится буфер переменной длины и без цикла.

string double_to_hex_string(double d)
{
    char converted[17];
    sprintf(converted, "%016llX", *((uint64_t*)&d));
    return std::string(converted);
}

Кстати,

Doubleзначение 0,61 представляется в памяти как 0,60999 (повторное возникновение).

не совсем корректно, повторяются только 14 девяток.(После этого есть другие цифры.) Если бы было бесконечное число девяток, это было бы точное представление 0,61!
Остальные ваши предположения в порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...