lib.rs 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // Calculate the shannon entropy of a given string for a given alphabeth
  2. pub fn shannon_entropy(s: &str) -> f32 {
  3. let mut entropy = 0f32;
  4. if s.is_empty() {
  5. return entropy;
  6. }
  7. for c in 0..=255u8 {
  8. let count = s.matches(char::from(c)).count() as f32;
  9. let slen = s.len() as f32;
  10. let p : f32 = count / slen;
  11. println!("{:?} {:?} {:?}", count, slen, p);
  12. if p > 0.0 {
  13. entropy += - p * p.log2();
  14. }
  15. }
  16. entropy
  17. }
  18. // Calculate the shannon entropy of a given string detecting the used alphabeth
  19. pub fn str_shannon_entropy(s: &str) -> f32 {
  20. let mut entropy = 0f32;
  21. if s.is_empty() {
  22. return entropy;
  23. }
  24. entropy = 1f32;
  25. entropy
  26. }
  27. // Tests
  28. #[cfg(test)]
  29. mod tests {
  30. use super::shannon_entropy;
  31. #[test]
  32. fn it_works() {
  33. let test_strings = vec![
  34. ("hello world", 2.8453512),
  35. ("hello worldd", 2.8553884),
  36. ("a", 0.0),
  37. ("", 0.0),
  38. ];
  39. for (test, answer) in test_strings {
  40. let entropy: f32 = shannon_entropy(test);
  41. assert_eq!(entropy, answer);
  42. }
  43. }
  44. #[test]
  45. fn test_entropy_empty() {
  46. let h = shannon_entropy("");
  47. assert_eq!(h, 0.0);
  48. }
  49. #[test]
  50. fn test_entropy_a() {
  51. let h = shannon_entropy("a");
  52. assert_eq!(h, 0.0);
  53. }
  54. #[test]
  55. fn test_entropy_aaaaa() {
  56. let h = shannon_entropy("aaaaa");
  57. assert_eq!(h, 0.0);
  58. }
  59. #[test]
  60. fn test_entropy_ab() {
  61. let h = shannon_entropy("ab");
  62. assert_eq!(h, 1.0);
  63. }
  64. #[test]
  65. fn test_entropy_aab() {
  66. let h = shannon_entropy("aab");
  67. assert_eq!(h, 0.9182958);
  68. }
  69. #[test]
  70. fn test_entropy_equal_distribution1() {
  71. let mut bytes = [0u8; 256];
  72. for i in 0..256 {
  73. bytes[i] = i as u8;
  74. }
  75. let h = shannon_entropy(&String::from_utf8_lossy(&bytes));
  76. assert_eq!(h, 8.0);
  77. }
  78. #[test]
  79. fn test_entropy_equal_distribution2() {
  80. let mut bytes = [0u8; 256*2];
  81. for i in 0..bytes.len() {
  82. bytes[i] = (i % 256) as u8;
  83. }
  84. let pippo = String::from(&bytes);
  85. println!("{:?} {:?}", pippo, pippo.len());
  86. let h = shannon_entropy(&pippo);
  87. assert_eq!(h, 8.0);
  88. }
  89. #[test]
  90. fn test_entropy_helloworld() {
  91. let h = shannon_entropy("hello, world");
  92. assert_eq!(h, 3.0220551);
  93. let h = shannon_entropy("hello world");
  94. assert_eq!(h, 2.8453512);
  95. }
  96. }