Ответ Жан-Батиста Юнеса является правильным, но я добавлю следующий пример, чтобы проиллюстрировать (имейте в виду, что он в javascript, только потому, что я быстро реализовал это для примера):
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
function getHashCollisions(collection, hashFunction) {
const collisionMap = new Map();
let count = 1;
let total = collection.length;
for (const point of collection) {
console.log(`calculating ${count++}/${total}`);
const currentHash = hashFunction(point);
const hashCount = collisionMap.has(currentHash) ? collisionMap.get(currentHash) +1 : 1;
collisionMap.set(currentHash, hashCount);
}
return collisionMap;
}
function generateDataset(rangeX, rangeY) {
const points = [];
let count = 1;
for (let x = 0; x < rangeX; x++) {
for (let y = 0; y < rangeY; y++) {
console.log(`generating ${count++} Point(${x};${y})`);
points.push(new Point(x, y));
}
}
return points;
}
function calculateAndGenerateReport(dataset, hashFunction, hashFunctionName) {
const hashes = getHashCollisions(dataset, hashFunction);
const totalCollisions = Array.from(hashes.values()).filter(currentCollisionCount => currentCollisionCount > 1).length;
const highestCollisionCount = Array.from(hashes.values()).reduce((currentHighest, current) => current > currentHighest ? current : currentHighest) - 1;
return `${hashFunctionName}: ${totalCollisions} collisions, highest collision count: ${highestCollisionCount}`;
}
const dataset = generateDataset(100, 100);
const literalHashesReport = calculateAndGenerateReport(dataset, point => point.x + point.y, "literal hash function:");
const onePrimeHashesReport = calculateAndGenerateReport(dataset, point => 31 * point.x + point.y, "one prime multiplication hash function:");
const twoPrimesHashesReport = calculateAndGenerateReport(dataset, point => 31 * point.x + 37 * point.y, "two primes multiplication hash function:");
const twoLargePrimesHashesReport = calculateAndGenerateReport(dataset, point => 8191 * point.x + 131071 * point.y, "two large primes multiplication hash function:");
console.log(literalHashesReport);
console.log(onePrimeHashesReport);
console.log(twoPrimesHashesReport);
console.log(twoLargePrimesHashesReport)
Результат:
literal hash function: 197 collisions, highest collision count: 99
one prime multiplication hash function: 3107 collisions, highest collision count: 3
two primes multiplication hash function: 3359 collisions, highest collision count: 2
two large primes multiplication hash function: 0 collisions, highest collision count: 0
Это показывает, что (простые) числа, которые мы выбираем для "вычисления" га sh, значительно уменьшают вероятность столкновений.