我需要将几个浮点数写到一个文本文件中,并用它们存储一个CRC32校验和。然后,当我从文本文件中读回浮点数时,我希望重新计算校验和,并将其与先前保存文件时计算的校验和进行比较。我的问题是校验和有时会失败。这是因为相等的浮点数可以由不同的位模式表示。为了完整起见,我将在接下来的段落中总结代码。
我改编了我在阅读this question后发现的this CRC32 algorithm。它看起来是这样的:
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将返回从文件读取的字符串中编码的浮点数的位表示,而不是用于将该字符串写入文件的浮点数的位表示。
所以,我的问题是:除了对字符串本身进行校验和之外,还有其他方法可以实现通过文本表示往返传递的浮点数校验和的目标吗?
感谢您的阅读!
发布于 2013-03-15 19:14:15
在更新CRC之前将你的数字规范化是可以接受的吗?因此,在保存时,您将获得您的数字的临时字符串版本(使用sprintf或任何与序列化格式匹配的内容),然后将此字符串转换回数字值,然后使用此结果更新CRC。这样,您就知道CRC将匹配反序列化后的值。
https://stackoverflow.com/questions/15429593
复制相似问题