いくつかの float をテキスト ファイルに書き込み、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 のテキスト表現を返すと仮定しましょう。
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 が、ファイルから読み取られた文字列にエンコードされた浮動小数点数の異なるビット表現を、その文字列をファイルに書き込むために使用された浮動小数点数のビット表現とは異なることです。
だから、私の質問は次のとおりです。文字列自体をチェックサムする以外に、テキスト表現を介して往復するフロートをチェックサムするという私の目標を達成する別の方法はありますか?
読んでくれてありがとう!