-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAvalancheEffect.cpp
95 lines (71 loc) · 3.11 KB
/
AvalancheEffect.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// This console app shows two different ways to calculate the number of bits
// changed in the hash hash_function values of a string when a single character
// is changed.
//
// The avalanche effect is a desirable function in hash functions where
// when the input is changed slightly the output changes significantly.
// This is useful in hashing because it increases the random distribution
// of hashes.
// See: http://en.wikipedia.org/wiki/Avalanche_effect
// Compiler: Microsoft Visual C++ Compiler Nov 2012 CTP (v120_CTP_Nov2012)
#include <string>
#include <iostream>
#include <bitset> // For bitset
#include <climits> // For CHAR_BIT
using namespace std;
// Example 1 - Comparing using a bit shift
void StdHashExample(std::string& str1, std::string& str2)
{
std::cout << std::endl << "Example 1 - %bit difference using std:hash" << std::endl;
std::hash<std::string> hash_function;
size_t str1_hash = hash_function(str1);
std::cout << "String 1: " << str1 << " , Hash: " << str1_hash << std::endl;
size_t str2_hash = hash_function(str2);
std::cout << "String 2: " << str2 << " , Hash: " << str2_hash << std::endl;
auto difference = str1_hash ^ str2_hash; // XOR to show what has changed
int count = 0;
auto total_bits = sizeof(difference) * CHAR_BIT; // Example: sizeof(3.33) * CHAR_BIT; gives the number of bits for a float
std::cout << "Number of bits: " << total_bits << std::endl << "XOR: ";
for (auto i = 0; i < total_bits; ++i) {
std::cout << (difference & 1);
count += (difference & 1); // (difference & 1) gives bit in position 1
difference >>= 1; // shift bits right by one
}
std::cout << std::endl << "Bits changed: " << count << " , % bits changed: " << (float) count / total_bits * 100 << std::endl;
};
// A rather questionable additive hash
unsigned AdditiveHash(std::string& key, unsigned len)
{
unsigned int hash = 0;
unsigned i;
for ( i = 0; i < len; i++)
hash += (unsigned char) key[i];
return hash;
};
// Example 2 - Comparing using a bitset
void AdditiveHashExample(std::string& str1, std::string& str2)
{
std::cout << std::endl << "Example 2 - %bit difference using questionable additive hash" << std::endl;
unsigned str1_hash = AdditiveHash(str1, 15);
std::cout << "String 1: " << str1 << " , Hash: " << str1_hash << std::endl;
bitset<32> hash1_bitset (str1_hash);
unsigned str2_hash = AdditiveHash(str2, 15);
std::cout << "String 2: " << str2 << " , Hash: " << str2_hash << std::endl;
bitset<32> hash2_bitset (str2_hash);
auto difference = hash1_bitset ^ hash2_bitset; // XOR to show what has changed
int count = 0;
auto total_bits = sizeof(difference) * CHAR_BIT;
std::cout << "Number of bits: " << total_bits << std::endl << "XOR: ";
for (auto i = 0 ; i < total_bits ; i++) {
std::cout << difference[i];
count += (difference[i]) ? 1 : 0;
}
std::cout << std::endl << "Bits changed: " << count << " , % bits changed: " << (float) count / total_bits * 100 << std::endl;
};
int main()
{
std::string str1 = "This is a test!";
std::string str2 = "This is a test.";
StdHashExample(str1, str2);
AdditiveHashExample(str1, str2);
}