Мне нужно записать пару поплавков в текстовый файл и сохранить с ними контрольную сумму CRC32. Затем, когда я читаю поплавки из текстового файла, я хочу пересчитать контрольную сумму и сравнить ее с той, которая была вычислена ранее при сохранении файла. Моя проблема в том, что контрольная сумма иногда не работает. Это связано с тем, что одинаковые числа с плавающей запятой могут быть представлены разными битовыми комбинациями. Для полноты я подытожу код в следующих абзацах.
Я адаптировал это Алгоритм CRC32, который я нашел после прочтения этого вопроса. Вот как это выглядит:
uint32_t updC32(uint32_t octet, uint32_t crc) {
return CRC32Tab[(crc ^ octet) & 0xFF] ^ (crc >> 8);
}
template <typename T>
uint32_t updateCRC32(T s, uint32_t crc) {
const char* buf = reinterpret_cast<const char*>(&s);
size_t len = sizeof(T);
for (; len; --len, ++buf)
crc = updC32(static_cast<uint32_t>(*buf), crc);
return crc;
}
CRC32Tab
содержит точно такие же значения, как большой массив в файле, указанном выше.
Это сокращенная версия того, как я записываю числа с плавающей запятой в файл и вычисляю контрольную сумму:
float x, y, z;
// set them to some values
uint32_t crc = 0xFFFFFFFF;
crc = Utility::updateCRC32(x, crc);
crc = Utility::updateCRC32(y, crc);
crc = Utility::updateCRC32(z, crc);
const uint32_t actualCrc = ~crc;
// stream is a FILE pointer, and I don't mind the scientific representation
fprintf(stream, " ( %g %g %g )", x, y, z);
fprintf(stream, " CRC %u\n", actualCrc);
Я прочитал значения обратно из файла следующим образом. На самом деле это намного сложнее, так как файл имеет более сложный синтаксис и должен быть проанализирован, но давайте предположим, что getNextFloat()
возвращает текстовое представление каждого числа с плавающей запятой, написанного ранее.
float x = std::atof(getNextFloat());
float y = std::atof(getNextFloat());
float z = std::atof(getNextFloat());
uint32_t crc = 0xFFFFFFFF;
crc = Utility::updateCRC32(x, crc);
crc = Utility::updateCRC32(y, crc);
crc = Utility::updateCRC32(z, crc);
const uint32_t actualCrc = ~crc;
const uint32_t fileCrc = // read the CRC from the file
assert(fileCrc == actualCrc); // fails often, but not always
Источником этой проблемы является то, что std::atof вернет другое битовое представление числа с плавающей запятой, закодированное в строке, которая была прочитана из файла, чем битовое представление числа с плавающей запятой, которое использовалось для записи этой строки в файл.
Итак, мой вопрос: есть ли другой способ достичь моей цели контрольной суммы поплавков, которые передаются через текстовое представление, кроме контрольной суммы самих строк?
Спасибо за чтение!