Пример #1
0
        /// <summary>
        /// Кодирует заданную исходную последовательность символов с помощью указанных основания и словаря частот встречаемости символов.
        /// </summary>
        /// <exception cref="ArgumentNullException">Исключение, которое выдается если <paramref name="source"/> или <paramref name="occurrenceFrequencies"/> равен null.</exception>
        /// <exception cref="ArithmeticCodingException">Исключение, которое выдается при отсутствии символа из исходной последовательности в словаре частот встречаемости символов.</exception>
        /// <param name="source">Исходная последовательность символов.</param>
        /// <param name="occurrenceFrequencies">Словарь частот встречаемости символов.</param>
        /// <param name="radix">Основание.</param>
        /// <returns>Арифметическое значение.</returns>
        public static ArithmeticValue Encode(char[] source, IReadOnlyDictionary <char, int> occurrenceFrequencies, int radix)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            if (occurrenceFrequencies == null)
            {
                throw new ArgumentNullException(nameof(occurrenceFrequencies));
            }

            var cumulativeFrequencies = ArithmeticDictionary.GetEncodingCumulativeFrequencies(occurrenceFrequencies);
            var lower = new BigInteger(0);
            var pf    = new BigInteger(1);

            foreach (var symbol in source)
            {
                if (!occurrenceFrequencies.ContainsKey(symbol))
                {
                    throw new ArithmeticCodingException($"Символ '{symbol}' (код - {(int)symbol}) не найден в словаре частот символов.");
                }

                lower = lower * source.Length + cumulativeFrequencies[symbol] * pf;
                pf   *= occurrenceFrequencies[symbol];
            }

            var upper    = lower + pf;
            var power    = CodingHelper.GetPower(pf, radix);
            var mantissa = (upper - 1) / BigInteger.Pow(radix, power);

            return(new ArithmeticValue(occurrenceFrequencies, mantissa, radix, power));
        }