13,005
回編集
(→CRC-16) |
|||
149行目: | 149行目: | ||
// 結果を4桁の16進数として表示 | // 結果を4桁の16進数として表示 | ||
Console.WriteLine($"CRC-16: 0x{crcValue:X4}"); | Console.WriteLine($"CRC-16: 0x{crcValue:X4}"); | ||
</syntaxhighlight> | |||
<br><br> | |||
== CRC-32 == | |||
標準的なCRC-32の生成多項式として0xEDB88320 (反転された0x04C11DB7, 4[byte]で行う) を使用する。<br> | |||
これは、一般的なCRC-32-IBM (別名 : CRC-32、PKZIP CRC-32) の規格である。<br> | |||
<br> | |||
CRC-32の生成多項式は、<math>x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^{8} + x^{7} + x^{5} + x^{4} + x^{2} + x + 1</math> である。<br> | |||
<br> | |||
* 最終XOR値 : 0xFFFFFFFF (ビット反転による) | |||
*: CRC計算の最後のステップとして、計算結果と0xFFFFFFFFとのXOR演算を行うことを意味する。 | |||
*: この操作は、計算された値の全てのビットを反転 (0→1、1→0) することと同じである。 | |||
** 目的 | |||
**: エラー検出能力を向上させる。 | |||
**: 全てが0のデータの場合でも、意味のあるCRC値を生成する。 | |||
* 入力反転 : あり | |||
*: 各バイトのビット順序を反転して処理することを意味する。 | |||
*: 例 : 入力バイト10110001は、10001101として処理する。 | |||
*: ルックアップテーブルの生成時にこの処理が組み込まれる。 | |||
** 目的 | |||
**: シリアル通信でのエンディアンの違いに対応する。 | |||
**: データの送受信時のビット順序の違いを吸収する。 | |||
* 出力反転 : あり | |||
*: 最終的なCRC値のビット順序を反転することを意味する。 | |||
*: これは、上記の"最終XOR値"の適用と同時に行われる。 | |||
** 目的 | |||
**: ハードウェア実装との互換性を確保する。 | |||
**: シフトレジスタベースの実装との整合性 | |||
<br> | |||
上記の操作は、CRC-32-IBMの規格を定義する重要な要素であり、以下に示すようなメリットがある。<br> | |||
* 異なるハードウェア・ソフトウェア間での互換性の確保 | |||
* 強力なエラー検出能力の実現 | |||
* データの先頭・末尾での特殊なビットパターンへの対応 | |||
* 実装の簡略化 (特に、ハードウェア実装において) | |||
<br> | |||
以下の例では、ルックアップテーブルを使用して計算を高速化している。<br> | |||
初期値として0xFFFFFFFFを使用して、最終的にビット反転を行う。<br> | |||
<br> | |||
<syntaxhighlight lang="c#"> | |||
public class CRC32 | |||
{ | |||
private readonly uint[] table; | |||
private const uint polynomial = 0xEDB88320; | |||
public CRC32() | |||
{ | |||
table = new uint[256]; | |||
// CRCテーブルの生成 | |||
for (uint i = 0; i < 256; i++) | |||
{ | |||
uint temp = i; | |||
for (int j = 0; j < 8; j++) | |||
{ | |||
if ((temp & 1) == 1) | |||
{ | |||
temp = (temp >> 1) ^ polynomial; | |||
} | |||
else | |||
{ | |||
temp >>= 1; | |||
} | |||
} | |||
table[i] = temp; | |||
} | |||
} | |||
public uint Calculate(byte[] data) | |||
{ | |||
uint crc = 0xFFFFFFFF; | |||
// CRC値の計算 | |||
foreach (byte b in data) | |||
{ | |||
byte index = (byte)((crc & 0xFF) ^ b); | |||
crc = (crc >> 8) ^ table[index]; | |||
} | |||
return ~crc; // 最終的なビット反転 | |||
} | |||
} | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c#"> | |||
// 使用例 | |||
// CRC-32を計算するためのテストデータ | |||
string text = "Hello, World!"; | |||
// 文字列をUTF-8でエンコードしてバイト配列に変換 | |||
byte[] data = System.Text.Encoding.UTF8.GetBytes(text); | |||
// CRC-32値を計算 | |||
CRC32 crc32 = new CRC32(); | |||
uint crcValue = crc32.Calculate(data); | |||
// 結果を8桁の16進数として表示 | |||
Console.WriteLine($"CRC-32: {crcValue:X8}"); | |||
</syntaxhighlight> | </syntaxhighlight> | ||
<br><br> | <br><br> |