/// <summary> /// Получает энтропии исходного и закодированного сообщений и вычисляет для них коэффициент избыточности. /// </summary> /// <exception cref="ArgumentNullException">Исключение, которое выдается когда <paramref name="value"/> равен null.</exception> /// <param name="value">Значение арифметического кодирования.</param> /// <returns>Коэффициент избыточности.</returns> public static double GetRedundantRatio(ArithmeticValue value) { var sourceEntropy = GetEntropy(value.OccurrenceFrequencies); var encodedEntropy = GetEntropy(value); return(GetRedundantRatio(sourceEntropy, encodedEntropy)); }
/// <summary> /// Получает энтропию закодированного сообщения как двоичного источника. /// </summary> /// <exception cref="ArgumentNullException">Исключение, которое выдается при <paramref name="value"/> равным null.</exception> /// <param name="value">Арифметическое значение.</param> /// <returns>Энтропию закодированного сообщения как двоичного источника.</returns> public static double GetEntropy(ArithmeticValue value) { if (value == null) { throw new ArgumentNullException(nameof(value)); } var bits = value.ToBits(); var countZeros = 0; var countOne = 0; foreach (var bit in bits) { if (bit) { countOne++; } else { countZeros++; } } var probZeros = countZeros / (double)(countZeros + countOne); var probOne = 1 - probZeros; return(probZeros * Math.Log(probZeros, 2) * -1 + probOne * Math.Log(probOne, 2) * -1); }
/// <summary> /// Получает коэффициент сжатия. /// </summary> /// <exception cref="ArgumentNullException">Исключение, которое выдается если <paramref name="value"/> равен null.</exception> /// <exception cref="ArgumentOutOfRangeException">Исключение, которое выдается когда <paramref name="bitsForOneSymbol"/> меньше 1.</exception> /// <param name="value">Значение арифметического кодирования.</param> /// <param name="bitsForOneSymbol">Бит, приходящихся на один символ в исходном сообщении.</param> /// <returns>Коэффициент сжатия.</returns> public static double GetCompressionRatio(ArithmeticValue value, int bitsForOneSymbol = 8) { if (value == null) { throw new ArgumentNullException(nameof(value)); } if (bitsForOneSymbol < 1) { throw new ArgumentOutOfRangeException(nameof(bitsForOneSymbol)); } var totalSymbols = value.OccurrenceFrequencies.Values.Sum(); return(totalSymbols * bitsForOneSymbol / (double)value.ToBits().Length); }
/// <summary> /// Создает новый файл по указанному пути и записывает туда словарь частот встречаемости символов и арифметический код. /// </summary> /// <exception cref="ArgumentNullException">Исключение, которое выдается если указанный код равен null.</exception> /// <exception cref="IOException">Исключение, которое выдается в случае невозможности записи в файл.</exception> /// <param name="path">Путь сохранения.</param> /// <param name="value">Арифметическое значение.</param> public static void Write(string path, ArithmeticValue value) { if (value == null) { throw new ArgumentNullException(nameof(value)); } using (var bw = new BinaryWriter(File.OpenWrite(path))) { bw.Write(value.OccurrenceFrequencies.Count); foreach (var keyValuePair in value.OccurrenceFrequencies) { bw.Write(keyValuePair.Key); bw.Write(keyValuePair.Value); } bw.Write(value.ToBytes()); } }