Я пишу код для вычисления энтропии строки с энтропией Шеннона.
Dim entropytext As String = Result.Text
Dim theresult = entropytext.GroupBy(Function(o) o) _
.Select(Function(o) New With {.Count = o.Count(), .Character = o.Key}) _
.GroupBy(Function(o) o.Count, Function(o) o.Character) _
.OrderByDescending(Function(o) o.Key)
Dim totalEntropy As Double = 0
Dim partialEntropy As Double
Dim partialP As Double
For Each item In theresult
Console.Write(item.Key & " of chars: ")
For Each character In item
Console.Write(character)
Next
partialP = item.Key / entropytext.Count
Console.Write(". p of each " & partialP & ", total p = " & item.Count * partialP)
partialEntropy = partialP * Math.Log(partialP) * item.Count
totalEntropy += partialEntropy
Console.WriteLine()
Next
totalEntropy *= -1
TextBox1.Text = totalEntropy & " Bits"
End Sub
Математика:
Entropy = -∑(P_xlog(P_x))
P_x = N_x/∑(N_x)
где P_x — вероятность появления буквы x,
а N_x – количество букв x.
So,
textbox1 ='AATC'
Entropy (textbox1)=-([2/4 log(2/4)]+[1/4 log (1/4)]+[1/4 log (1/4)])
= 1.0397
Но это слишком мало... согласно (http://www.shannonentropy.netmark.pl/ а>) должно быть "1,5". Что я делаю неправильно? Заранее спасибо!!
По сути, это должно работать так... но я не разбираюсь в до-диезе...
public static double ShannonEntropy(string s)
{
var map = new Dictionary<char, int>();
foreach (char c in s)
{
if (!map.ContainsKey(c))
map.Add(c, 1);
else
map[c] += 1;
}
double result = 0.0;
int len = s.Length;
foreach (var item in map)
{
var frequency = (double)item.Value / len;
result -= frequency * (Math.Log(frequency) / Math.Log(2));
}
return result;
}