次の単純なスクリプトは、2 つのランダムな 20 バイト シーケンスをフェッチし、CRC16 を計算し、衝突があるかどうかをチェックする無限ループを実行します。このループの事実上の継続的な評価により、衝突の割合が推定されます。
#!/usr/bin/env perl
use Digest::CRC qw(crc16);
open(my $f, '<', '/dev/urandom');
my $n = 0;
my $coll = 0;
while (1) {
read $f, $randstr1, 20;
read $f, $randstr2, 20;
my $crc1 = crc16($randstr1);
my $crc2 = crc16($randstr2);
$n++;
$coll++ if $crc1 == $crc2;
printf "percent of collisions = %.6f%%\n", $coll * 100.0 / $n if ($n % 100000 == 0);
}
私のコンピューターで取得したものから、衝突の割合は約0.0016%
(または1e-5
"100_000 分の 1") であると思われます。これは、16 ビット ハッシュの理想的なハッシュ分布 (2^16 / 2^160)。
更新: 20 バイトは完全にランダムなバイトではなく、[a-z0-9]
. そのアルファベットでの衝突を推定する更新版は次のとおりです。
#!/usr/bin/env perl
use Digest::CRC qw(crc16);
my $n = 0;
my $coll = 0;
my @chars = ('a'..'z', '0'..'9');
sub randstr() {
my $res;
foreach (1..20) { $res .= $chars[rand @chars]; }
return $res;
}
while (1) {
my $crc1 = crc16(randstr());
my $crc2 = crc16(randstr());
$n++;
$coll++ if $crc1 == $crc2;
printf "percent of collisions = %.4f%%\n", $coll * 100.0 / $n if ($n % 100000 == 0);
}
ほぼ同じ結果が得られます0.0016%
。