<?xml version="1.0"?>
<?xml-stylesheet type="text/css" href="https://vscripts.ru/w/skins/common/feed.css?303"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>https://vscripts.ru/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Myachikov</id>
		<title>Модулярная арифметика - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="https://vscripts.ru/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Myachikov"/>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Myachikov"/>
		<updated>2026-05-27T21:59:46Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.23.17</generator>

	<entry>
		<id>https://vscripts.ru/w/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%A8%D1%91%D0%BD%D1%85%D0%B0%D0%B3%D0%B5_%E2%80%94_%D0%A8%D1%82%D1%80%D0%B0%D1%81%D1%81%D0%B5%D0%BD%D0%B0_(New)</id>
		<title>Метод умножения Шёнхаге — Штрассена (New)</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%A8%D1%91%D0%BD%D1%85%D0%B0%D0%B3%D0%B5_%E2%80%94_%D0%A8%D1%82%D1%80%D0%B0%D1%81%D1%81%D0%B5%D0%BD%D0%B0_(New)"/>
				<updated>2014-02-17T07:27:57Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Шёнхаге - Штрассена''' - асимптотически быстрый алгоритм умножения больших чисел. Он был разработан Арнольдом Шёнхаге и Фолькером Штрассеном в 1971. Сложность алгоритма в нотации &amp;quot;О - большого&amp;quot; составляет O(''N''&amp;amp;nbsp;log&amp;amp;nbsp;''N''&amp;amp;nbsp;log&amp;amp;nbsp;log&amp;amp;nbsp;''N''). Алгоритм&lt;br /&gt;
рекурсивно использует быстрое преобразование Фурье над кольцом из  2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 элементов, специальный тип дискретного преобразования Фурье - теоретико-числовое преобразование.&lt;br /&gt;
&lt;br /&gt;
Алгоритм Шёнхаге - Штрассена являлся наиболее быстрым асимптотически известным методом умножения с 1971 до 2007, когда Фюрером был предложен более быстрый метод. Тем не менее, алгоритм Фюрера в настоящее время имеет преимущество только для астрономически больших чисел и не используется на практике.&lt;br /&gt;
&lt;br /&gt;
На практике алгоритм Шёнхаге - Штрассена начинает превосходить в скорости старые методы, такие как алгоритм Карацубы и алгоритм Тоома-Кука для чисел между 2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;15&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt; и 2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;17&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt; (от 10,000 до 40,000 десятичных разрядов).&lt;br /&gt;
&lt;br /&gt;
Приложения алгоритма Шёнхаге - Штрассена включают в себя как чисто математические задачи, такие как поиск простых чисел Мерсенна и вычисление цифр числа ''π'', так и практические, такие как вычисление подстановки Кронекера, в которой умножение многочленов с целыми коэффициентами можно эффективно заменить умножением больших чисел; это используется на практике by GMP-ECM для факторизации целых чисел методом эллиптических кривых Ленстры.&lt;br /&gt;
&lt;br /&gt;
== Теория ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Свертка ===&lt;br /&gt;
Допустим, что мы перемножаем числа 123 и 456 «в столбик», однако без выполнения переноса. Результат будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|   ||        || 1 || 2 || 3&lt;br /&gt;
|-&lt;br /&gt;
|   || &amp;amp;times;|| 4 || 5 || 6&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   ||        || 6 || 12 || 18&lt;br /&gt;
|-&lt;br /&gt;
|   ||      5 || 10 || 15 ||&lt;br /&gt;
|-&lt;br /&gt;
| 4 ||      8 || 12 ||    ||&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 4 ||     13 || 28 || 27 || 18&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Эта последовательность (4, 13, 28, 27, 18) называется ''ациклической'' или ''линейной свёрткой'' от последовательностей (1,2,3) и (4,5,6). Зная ациклическую свёртку двух последовательностей, рассчитать произведение несложно: достаточно выполнить перенос (например, в самом правом столбце, мы оставляем 8 и добавляем 1 к столбцу, содержащему 27). В нашем примере это приводит к результату 56088.&lt;br /&gt;
&lt;br /&gt;
Есть и другие типы свёрток, которые могут быть полезны. Допустим, что входящие последовательности содержат ''n'' элементов (в примере — 3). Тогда результирующая линейная свёртка содержит ''n'' + ''n'' &amp;amp;minus; 1 элементов; если мы возьмём самый правый столбец ''n'' элементов и добавим самый левый столбец ''n'' &amp;amp;minus; 1 ', в результате мы получим циклическую свёртку:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|   || 28 || 27 || 18&lt;br /&gt;
|-&lt;br /&gt;
| + ||    ||  4 || 13&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   || 28 || 31 || 31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Если мы произведём перенос при циклическом свёртывании, результат будет тот же, что и при произведении чисел по модулю B&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;minus;&amp;amp;nbsp;1 (в данном примере это 10&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;minus;&amp;amp;nbsp;1 = 999). Выполним перенос по (28, 31, 31) и получим 3141, при этом 3141 ≡ 56088 (mod 999).&lt;br /&gt;
&lt;br /&gt;
Наоборот, если мы возьмём самый правый столбец ''n'' элементов и ''вычтем'' самый левый столбец ''n''&amp;amp;minus;1 элементов, то в результате мы получим обратную свёртку:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|         || 28 || 27 || 18&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;minus; ||    ||  4 || 13&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|         || 28 || 23 ||  5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Если мы произведём перенос при обратном свёртывании, то результат будет тот же, что и при произведении чисел по модулю B&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1. В данном примере, 10&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 = 1001, выполним перенос по (28, 23, 5) и получим 3035, при этом 3035 ≡ 56088 (mod 1001). Обратная свёртка может содержать отрицательные числа, которые могут быть убраны во время переноса, используя ту же технику, что и при длинных вычитаниях.&lt;br /&gt;
&lt;br /&gt;
=== Теорема о свёртке ===&lt;br /&gt;
&lt;br /&gt;
Как и другие методы, основанные на быстром преобразовании Фурье, алгоритм Шёнхаге - Штрассена в корне зависит от теоремы о свёртке, которая обеспечивает эффективный способ посчитать циклическую свёртку двух последовательностей. Её идея состоит в следующем:&lt;br /&gt;
&lt;br /&gt;
: Циклическая свёртка двух векторов может быть найдена через [[дискретное преобразование Фурье]] (ДПФ) каждого из них, путём произведения результирующих векторов элемент за элементом, с последующим обратным преобразованием Фурье (ОДПФ).&lt;br /&gt;
&lt;br /&gt;
Или через формулы:&lt;br /&gt;
&lt;br /&gt;
: CyclicConvolution(X, Y) = IDFT(DFT(X) &amp;amp;middot; DFT(Y)), где:&lt;br /&gt;
:: CyclicConvolution — ''циклическая свертка'',&lt;br /&gt;
:: DFT — ''дискретное преобразование Фурье'',&lt;br /&gt;
:: IDFT — ''обратное дискретное преобразование Фурье''.&lt;br /&gt;
&lt;br /&gt;
Если мы посчитаем ДПФ и ОДПФ, используя быстрое преобразование Фурье, и вызовем наш алгоритм перемножения рекурсивно, чтобы перемножить входы(?) преобразованных векторов DFT(X) и DFT(Y), то в результате мы получим эффективный алгоритм для расчёта циклической свёртки.&lt;br /&gt;
&lt;br /&gt;
В этом алгоритме, гораздо эффективней считать ''обратную циклическую'' свёртку; как оказывается, немного модифицированная версия теоремы о свёртке может позволить и это. Предположим, что вектора X и Y имеют длину ''n'', и ''a'' — примитивный корень порядка 2''n'' (это означает, что ''a''&amp;lt;sup&amp;gt;2''n''&amp;lt;/sup&amp;gt; = 1 и все меньшие степени ''a'' не равны 1). Таким образом мы можем определить третий вектор ''A'', называемый ''вектор веса'', обладающий следующими свойствами:&lt;br /&gt;
[[Файл:DIT-FFT-butterfly.png|мини|Операция «[[бабочка (БПФ)|бабочка]]».]]&lt;br /&gt;
&lt;br /&gt;
: ''A'' = (''a''&amp;lt;sup&amp;gt;''j''&amp;lt;/sup&amp;gt;), 0 &amp;amp;le; ''j'' &amp;lt; ''n''&lt;br /&gt;
: ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt; = (''a''&amp;lt;sup&amp;gt;&amp;amp;minus;j''&amp;lt;/sup&amp;gt;), 0 &amp;amp;le; ''j'' &amp;lt; ''n''&lt;br /&gt;
&lt;br /&gt;
Теперь мы можем записать:&lt;br /&gt;
&lt;br /&gt;
: NegacyclicConvolution(''X'', ''Y'') = ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt; &amp;amp;middot; IDFT(DFT(''A'' &amp;amp;middot; ''X'') &amp;amp;middot; DFT(''A'' &amp;amp;middot; ''Y'')), где&lt;br /&gt;
:: NegacyclicConvolution — ''Обратная циклическая свертка'',&lt;br /&gt;
:: DFT — ''дискретное преобразование Фурье'',&lt;br /&gt;
:: IDFT — ''обратное дискретное преобразование Фурье''.&lt;br /&gt;
&lt;br /&gt;
Другими словами, это то же самое за исключением того, что входящие векторы умножены на ''A'', а результат умножен на ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Выбор кольца ===&lt;br /&gt;
&lt;br /&gt;
Дискретное преобразование Фурье — абстрактная операция, которая может быть выполнена в любом алгебраическом [[Кольцо (математика)|кольце]]; обычно оно берётся из поля комплексных чисел, но фактически использовать комплексную арифметику с достаточной точностью, чтобы обеспечить точные результаты, медленно и неэффективно. Вместо этого мы можем использовать теоретико-числовое преобразование, которое производит преобразование в поле целых чисел по модулю N для некоторого целого N.&lt;br /&gt;
&lt;br /&gt;
Так же как есть примитивные корни единицы любого порядка на комплексной плоскости, при любом заданном ''n'' мы можем выбрать подходящее N такое, что ''b'' — примитивный корень единицы порядка ''n'' в поле целых чисел по модулю N (другими словами, ''b''&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt; ≡ 1 (mod N), и все меньшие степени ''b'' не равны 1 mod N).&lt;br /&gt;
&lt;br /&gt;
Алгоритм тратит большую часть времени на рекурсивное выполнение произведения меньших чисел; в простом варианте алгоритма это происходит в ряде мест:&lt;br /&gt;
&lt;br /&gt;
# Внутри алгоритма быстрого преобразования Фурье, примитивный корень единицы ''b'' неоднократно возводится в степень и умножается на другие числа.&lt;br /&gt;
# При возведении в степень примитивного корня единицы ''a'' для получения вектора веса A с последующим умножением векторов A или A&amp;lt;sup&amp;gt;−1&amp;lt;/sup&amp;gt; на другие вектора.&lt;br /&gt;
# При выполнении последовательного перемножения преобразованных векторов.&lt;br /&gt;
&lt;br /&gt;
Ключевой момент — выбрать N, модуль, равный 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 для некоторого целого ''n''. У этого способа есть ряд преимуществ в ряде стандартных систем, в которых большие целые числа представлены в двоичном виде:&lt;br /&gt;
&lt;br /&gt;
* Любое число может быть быстро уменьшено по модулю 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 используя только сдвиг и сложение.&lt;br /&gt;
* Любые примитивные корни единицы в этом кольце могут быть записаны в форме 2&amp;lt;sup&amp;gt;''k''&amp;lt;/sup&amp;gt;; соответственно мы можем умножать или делить любое число на корень из единицы используя сдвиг.&lt;br /&gt;
* Поэлементное рекурсивное перемножение преобразованный векторов может быть выполнено, используя обратную свёртку, которая работает быстрее, чем ациклическая свёртка, и в которой уже есть уменьшение результата &lt;br /&gt;
по модулю 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1.&lt;br /&gt;
&lt;br /&gt;
=== Пример ===&lt;br /&gt;
Следующий пример иллюстрирует работу алгоритма.&lt;br /&gt;
Положим задано два числа: X и Y, каждое длиной 8 бит. Требуется найти значение RES = (X*Y) mod 2&amp;lt;sup&amp;gt;N&amp;lt;/sup&amp;gt;+1&lt;br /&gt;
Возьмём для определённости X = Y = 129&amp;lt;sub&amp;gt;10&amp;lt;/sub&amp;gt; = 1000 0001&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. &lt;br /&gt;
Выберем N = 8 + 8 = 16.&lt;br /&gt;
* Этап 1. Разбиение чисел на K = 4 слов длины M = 4 бита: &lt;br /&gt;
**Дополним числа нулями до длины N = 16 и разобьём на слова. Получим две последовательности (в данном примере идентичные): {0001, 1000, 0000, 0000}. Или в десятичном виде: {3, 8, 0, 0} (слова расположены в порядке от младших бит к старшим). Все операции далее выполняются по модулю 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1, где n выбирается из условия n &amp;gt;= 2*M + log2(K) и является степенью двойки, то есть в нашем случае n &amp;gt;= 2*4 + 2 = 10, n = 16.&lt;br /&gt;
&lt;br /&gt;
* Этап 2. Вычисление свёртки двух последовательностей: &lt;br /&gt;
** Этап 2.1 Умножение последовательностей на весовые коэффициенты. 2K-ый корень из единицы в кольце из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1 элементов равен 2&amp;lt;sup&amp;gt;2n/2K&amp;lt;/sup&amp;gt; = 2&amp;lt;sup&amp;gt;4&amp;lt;/sup&amp;gt; = 16. Результат умножения на вектор весовых коэффициентов в десятичном виде: {1, 128, 0, 0}.&lt;br /&gt;
**Этап 2.2 Прямое преобразование Фурье над кольцом из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. K-ый корень из единицы в кольце вычетов по модулю 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1 равен 2&amp;lt;sup&amp;gt;2n/2K&amp;lt;/sup&amp;gt; = 2&amp;lt;sup&amp;gt;4&amp;lt;/sup&amp;gt; = 256. Формула преобразования: &amp;lt;math&amp;gt;b_i = \sum^{K-1}_{j=0}{a_j\omega^{ij}}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; \omega &amp;lt;/math&amp;gt; - К-тый корень из единицы в кольце вычетов по модулю 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1. Результат: {129, 32769, 65410, 32770}.&lt;br /&gt;
**Этап 2.3 Покомпонентное произведение последовательностей в кольце из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. Результат: {16641, 49153, 16129, 49155}.&lt;br /&gt;
**Этап 2.4 Обратное преобразование Фурье над кольцом из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. Формула обратного преобразования: &amp;lt;math&amp;gt;b_i = \frac {1}{K} \sum^{K-1}_{j=0}{a_j\omega^{ij}}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; \frac {1}{K} &amp;lt;/math&amp;gt; - обратный к &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; по модулю 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1. Результат: {1, 256, 16384, 0}.&lt;br /&gt;
**Этап 2.5 Умножение последовательностей на коэффициенты, обратные к используемым в 2.1. Результат: {1, 16, 64, 0}.&lt;br /&gt;
* Этап 3. Выполнение операции переноса. Результат: {1, 0, 1, 4}. В двоичном виде: {0001, 0000, 0001, 0100}&lt;br /&gt;
* Этап 5. &amp;quot;Склейка&amp;quot; полученной последовательности, окончательный результат: 1010000001000&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 16641 = 129 * 129.&lt;br /&gt;
* Этап 5. Вычисление остатка по модулю 2&amp;lt;sup&amp;gt;N&amp;lt;/sup&amp;gt;+1. В данном случае 16641 = 16641 mod 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt;+1&lt;br /&gt;
&lt;br /&gt;
=== Описание ===&lt;br /&gt;
* [http://gmplib.org/manual/FFT-Multiplication.html#FFT-Multiplication Документация GMP LIB]&lt;br /&gt;
* [http://hal.archives-ouvertes.fr/docs/00/12/64/62/PDF/fft.pdf Статья A GMP-BASED IMPLEMENTATION OF SCHONHAGE-STRASSEN’S LARGE INTEGER MULTIPLICATION ALGORITHM]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Sch%C3%B6nhage%E2%80%93Strassen_algorithm Описание в английской Wikipedia]&lt;br /&gt;
&lt;br /&gt;
=== Исходники ===&lt;br /&gt;
[http://www.ginac.de/CLN/cln.git/?p=cln.git;a=blob;f=src/base/digitseq/cl_DS_mul_fftm.h;h=a984802ce039e8179a26fda2681a2e133dba6fbd;hb=refs/heads/master CLN - Class Library for Numbers]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/myachik/ss_mult/blob/master/ss_mult.cpp Вариант реализации алгоритма]&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%A8%D1%91%D0%BD%D1%85%D0%B0%D0%B3%D0%B5_%E2%80%94_%D0%A8%D1%82%D1%80%D0%B0%D1%81%D1%81%D0%B5%D0%BD%D0%B0_(New)</id>
		<title>Метод умножения Шёнхаге — Штрассена (New)</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%A8%D1%91%D0%BD%D1%85%D0%B0%D0%B3%D0%B5_%E2%80%94_%D0%A8%D1%82%D1%80%D0%B0%D1%81%D1%81%D0%B5%D0%BD%D0%B0_(New)"/>
				<updated>2014-02-06T08:57:56Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Шёнхаге - Штрассена''' - асимптотически быстрый алгоритм умножения больших чисел. Он был разработан Арнольдом Шёнхаге и Фолькером Штрассеном в 1971. Сложность алгоритма в нотации &amp;quot;О - большого&amp;quot; составляет O(''N''&amp;amp;nbsp;log&amp;amp;nbsp;''N''&amp;amp;nbsp;log&amp;amp;nbsp;log&amp;amp;nbsp;''N''). Алгоритм&lt;br /&gt;
рекурсивно использует быстрое преобразование Фурье над кольцом из  2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 элементов, специальный тип дискретного преобразования Фурье - теоретико-числовое преобразование.&lt;br /&gt;
&lt;br /&gt;
Алгоритм Шёнхаге - Штрассена являлся наиболее быстрым асимптотически известным методом умножения с 1971 до 2007, когда Фюрером был предложен более быстрый метод. Тем не менее, алгоритм Фюрера в настоящее время имеет преимущество только для астрономически больших чисел и не используется на практике.&lt;br /&gt;
&lt;br /&gt;
На практике алгоритм Шёнхаге - Штрассена начинает превосходить в скорости старые методы, такие как алгоритм Карацубы и алгоритм Тоома-Кука для чисел между 2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;15&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt; и 2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;17&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt; (от 10,000 до 40,000 десятичных разрядов).&lt;br /&gt;
&lt;br /&gt;
Приложения алгоритма Шёнхаге - Штрассена включают в себя как чисто математические задачи, такие как поиск простых чисел Мерсенна и вычисление цифр числа ''π'', так и практические, такие как вычисление подстановки Кронекера, в которой умножение многочленов с целыми коэффициентами можно эффективно заменить умножением больших чисел; это используется на практике by GMP-ECM для факторизации целых чисел методом эллиптических кривых Ленстры.&lt;br /&gt;
&lt;br /&gt;
== Теория ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Свертка ===&lt;br /&gt;
Допустим, что мы перемножаем числа 123 и 456 «в столбик», однако без выполнения переноса. Результат будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|   ||        || 1 || 2 || 3&lt;br /&gt;
|-&lt;br /&gt;
|   || &amp;amp;times;|| 4 || 5 || 6&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   ||        || 6 || 12 || 18&lt;br /&gt;
|-&lt;br /&gt;
|   ||      5 || 10 || 15 ||&lt;br /&gt;
|-&lt;br /&gt;
| 4 ||      8 || 12 ||    ||&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 4 ||     13 || 28 || 27 || 18&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Эта последовательность (4, 13, 28, 27, 18) называется ''ациклической'' или ''линейной свёрткой'' от последовательностей (1,2,3) и (4,5,6). Зная ациклическую свёртку двух последовательностей, рассчитать произведение несложно: достаточно выполнить перенос (например, в самом правом столбце, мы оставляем 8 и добавляем 1 к столбцу, содержащему 27). В нашем примере это приводит к результату 56088.&lt;br /&gt;
&lt;br /&gt;
Есть и другие типы свёрток, которые могут быть полезны. Допустим, что входящие последовательности содержат ''n'' элементов (в примере — 3). Тогда результирующая линейная свёртка содержит ''n'' + ''n'' &amp;amp;minus; 1 элементов; если мы возьмём самый правый столбец ''n'' элементов и добавим самый левый столбец ''n'' &amp;amp;minus; 1 ', в результате мы получим циклическую свёртку:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|   || 28 || 27 || 18&lt;br /&gt;
|-&lt;br /&gt;
| + ||    ||  4 || 13&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   || 28 || 31 || 31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Если мы произведём перенос при циклическом свёртывании, результат будет тот же, что и при произведении чисел по модулю B&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;minus;&amp;amp;nbsp;1 (в данном примере это 10&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;minus;&amp;amp;nbsp;1 = 999). Выполним перенос по (28, 31, 31) и получим 3141, при этом 3141 ≡ 56088 (mod 999).&lt;br /&gt;
&lt;br /&gt;
Наоборот, если мы возьмём самый правый столбец ''n'' элементов и ''вычтем'' самый левый столбец ''n''&amp;amp;minus;1 элементов, то в результате мы получим обратную свёртку:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|         || 28 || 27 || 18&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;minus; ||    ||  4 || 13&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|         || 28 || 23 ||  5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Если мы произведём перенос при обратном свёртывании, то результат будет тот же, что и при произведении чисел по модулю B&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1. В данном примере, 10&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 = 1001, выполним перенос по (28, 23, 5) и получим 3035, при этом 3035 ≡ 56088 (mod 1001). Обратная свёртка может содержать отрицательные числа, которые могут быть убраны во время переноса, используя ту же технику, что и при длинных вычитаниях.&lt;br /&gt;
&lt;br /&gt;
=== Теорема о свёртке ===&lt;br /&gt;
&lt;br /&gt;
Как и другие методы, основанные на быстром преобразовании Фурье, алгоритм Шёнхаге - Штрассена в корне зависит от теоремы о свёртке, которая обеспечивает эффективный способ посчитать циклическую свёртку двух последовательностей. Её идея состоит в следующем:&lt;br /&gt;
&lt;br /&gt;
: Циклическая свёртка двух векторов может быть найдена через [[дискретное преобразование Фурье]] (ДПФ) каждого из них, путём произведения результирующих векторов элемент за элементом, с последующим обратным преобразованием Фурье (ОДПФ).&lt;br /&gt;
&lt;br /&gt;
Или через формулы:&lt;br /&gt;
&lt;br /&gt;
: CyclicConvolution(X, Y) = IDFT(DFT(X) &amp;amp;middot; DFT(Y)), где:&lt;br /&gt;
:: CyclicConvolution — ''циклическая свертка'',&lt;br /&gt;
:: DFT — ''дискретное преобразование Фурье'',&lt;br /&gt;
:: IDFT — ''обратное дискретное преобразование Фурье''.&lt;br /&gt;
&lt;br /&gt;
Если мы посчитаем ДПФ и ОДПФ, используя быстрое преобразование Фурье, и вызовем наш алгоритм перемножения рекурсивно, чтобы перемножить входы(?) преобразованных векторов DFT(X) и DFT(Y), то в результате мы получим эффективный алгоритм для расчёта циклической свёртки.&lt;br /&gt;
&lt;br /&gt;
В этом алгоритме, гораздо эффективней считать ''обратную циклическую'' свёртку; как оказывается, немного модифицированная версия теоремы о свёртке может позволить и это. Предположим, что вектора X и Y имеют длину ''n'', и ''a'' — примитивный корень порядка 2''n'' (это означает, что ''a''&amp;lt;sup&amp;gt;2''n''&amp;lt;/sup&amp;gt; = 1 и все меньшие степени ''a'' не равны 1). Таким образом мы можем определить третий вектор ''A'', называемый ''вектор веса'', обладающий следующими свойствами:&lt;br /&gt;
[[Файл:DIT-FFT-butterfly.png|мини|Операция «[[бабочка (БПФ)|бабочка]]».]]&lt;br /&gt;
&lt;br /&gt;
: ''A'' = (''a''&amp;lt;sup&amp;gt;''j''&amp;lt;/sup&amp;gt;), 0 &amp;amp;le; ''j'' &amp;lt; ''n''&lt;br /&gt;
: ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt; = (''a''&amp;lt;sup&amp;gt;&amp;amp;minus;j''&amp;lt;/sup&amp;gt;), 0 &amp;amp;le; ''j'' &amp;lt; ''n''&lt;br /&gt;
&lt;br /&gt;
Теперь мы можем записать:&lt;br /&gt;
&lt;br /&gt;
: NegacyclicConvolution(''X'', ''Y'') = ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt; &amp;amp;middot; IDFT(DFT(''A'' &amp;amp;middot; ''X'') &amp;amp;middot; DFT(''A'' &amp;amp;middot; ''Y'')), где&lt;br /&gt;
:: NegacyclicConvolution — ''Обратная циклическая свертка'',&lt;br /&gt;
:: DFT — ''дискретное преобразование Фурье'',&lt;br /&gt;
:: IDFT — ''обратное дискретное преобразование Фурье''.&lt;br /&gt;
&lt;br /&gt;
Другими словами, это то же самое за исключением того, что входящие векторы умножены на ''A'', а результат умножен на ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Выбор кольца ===&lt;br /&gt;
&lt;br /&gt;
Дискретное преобразование Фурье — абстрактная операция, которая может быть выполнена в любом алгебраическом [[Кольцо (математика)|кольце]]; обычно оно берётся из поля комплексных чисел, но фактически использовать комплексную арифметику с достаточной точностью, чтобы обеспечить точные результаты, медленно и неэффективно. Вместо этого мы можем использовать теоретико-числовое преобразование, которое производит преобразование в поле целых чисел по модулю N для некоторого целого N.&lt;br /&gt;
&lt;br /&gt;
Так же как есть примитивные корни единицы любого порядка на комплексной плоскости, при любом заданном ''n'' мы можем выбрать подходящее N такое, что ''b'' — примитивный корень единицы порядка ''n'' в поле целых чисел по модулю N (другими словами, ''b''&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt; ≡ 1 (mod N), и все меньшие степени ''b'' не равны 1 mod N).&lt;br /&gt;
&lt;br /&gt;
Алгоритм тратит большую часть времени на рекурсивное выполнение произведения меньших чисел; в простом варианте алгоритма это происходит в ряде мест:&lt;br /&gt;
&lt;br /&gt;
# Внутри алгоритма быстрого преобразования Фурье, примитивный корень единицы ''b'' неоднократно возводится в степень и умножается на другие числа.&lt;br /&gt;
# При возведении в степень примитивного корня единицы ''a'' для получения вектора веса A с последующим умножением векторов A или A&amp;lt;sup&amp;gt;−1&amp;lt;/sup&amp;gt; на другие вектора.&lt;br /&gt;
# При выполнении последовательного перемножения преобразованных векторов.&lt;br /&gt;
&lt;br /&gt;
Ключевой момент — выбрать N, модуль, равный 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 для некоторого целого ''n''. У этого способа есть ряд преимуществ в ряде стандартных систем, в которых большие целые числа представлены в двоичном виде:&lt;br /&gt;
&lt;br /&gt;
* Любое число может быть быстро уменьшено по модулю 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 используя только сдвиг и сложение.&lt;br /&gt;
* Любые примитивные корни единицы в этом кольце могут быть записаны в форме 2&amp;lt;sup&amp;gt;''k''&amp;lt;/sup&amp;gt;; соответственно мы можем умножать или делить любое число на корень из единицы используя сдвиг.&lt;br /&gt;
* Поэлементное рекурсивное перемножение преобразованный векторов может быть выполнено, используя обратную свёртку, которая работает быстрее, чем ациклическая свёртка, и в которой уже есть уменьшение результата &lt;br /&gt;
по модулю 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1.&lt;br /&gt;
&lt;br /&gt;
=== Пример ===&lt;br /&gt;
Следующий пример иллюстрирует работу алгоритма.&lt;br /&gt;
Положим задано два числа: X и Y, каждое длиной 8 бит. Требуется найти значение RES = (X*Y) mod 2&amp;lt;sup&amp;gt;N&amp;lt;/sup&amp;gt;+1&lt;br /&gt;
Возьмём для определённости X = Y = 129&amp;lt;sub&amp;gt;10&amp;lt;/sub&amp;gt; = 1000 0001&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. &lt;br /&gt;
Выберем N = 8 + 8 = 16.&lt;br /&gt;
* Этап 1. Разбиение чисел на K = 4 слов длины M = 4 бита: &lt;br /&gt;
**Дополним числа нулями до длины N = 16 и разобьём на слова. Получим две последовательности (в данном примере идентичные): {0001, 1000, 0000, 0000}. Или в десятичном виде: {3, 8, 0, 0} (слова расположены в порядке от младших бит к старшим). Все операции далее выполняются по модулю 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1, где n выбирается из условия n &amp;gt;= 2*M + log2(K) и является степенью двойки, то есть в нашем случае n &amp;gt;= 2*4 + 2 = 10, n = 16.&lt;br /&gt;
&lt;br /&gt;
* Этап 2. Вычисление свёртки двух последовательностей: &lt;br /&gt;
** Этап 2.1 Умножение последовательностей на весовые коэффициенты. 2K-ый корень из единицы в кольце из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1 элементов равен 2&amp;lt;sup&amp;gt;2n/2K&amp;lt;/sup&amp;gt; = 2&amp;lt;sup&amp;gt;4&amp;lt;/sup&amp;gt; = 16. Результат умножения на вектор весовых коэффициентов в десятичном виде: {1, 128, 0, 0}.&lt;br /&gt;
**Этап 2.2 Прямое преобразование Фурье над кольцом из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. K-ый корень из единицы в кольце вычетов по модулю 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1 равен 2&amp;lt;sup&amp;gt;2n/2K&amp;lt;/sup&amp;gt; = 2&amp;lt;sup&amp;gt;4&amp;lt;/sup&amp;gt; = 256. Формула преобразования: &amp;lt;math&amp;gt;b_i = \sum^{K-1}_{j=0}{a_j\omega^{ij}}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; \omega &amp;lt;/math&amp;gt; - К-тый корень в кольце вычетов по модулю 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1. Результат: {129, 32769, 65410, 32770}.&lt;br /&gt;
**Этап 2.3 Покомпонентное произведение последовательностей в кольце из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. Результат: {16641, 49153, 16129, 49155}.&lt;br /&gt;
**Этап 2.4 Обратное преобразование Фурье над кольцом из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. Формула обратного преобразования: &amp;lt;math&amp;gt;b_i = \frac {1}{K} \sum^{K-1}_{j=0}{a_j\omega^{ij}}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; \frac {1}{K} &amp;lt;/math&amp;gt; - обратный к &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; по модулю 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1. Результат: {1, 256, 16384, 0}.&lt;br /&gt;
**Этап 2.5 Умножение последовательностей на коэффициенты, обратные к используемым в 2.1. Результат: {1, 16, 64, 0}.&lt;br /&gt;
* Этап 3. Выполнение операции переноса. Результат: {1, 0, 1, 4}. В двоичном виде: {0001, 0000, 0001, 0100}&lt;br /&gt;
* Этап 5. &amp;quot;Склейка&amp;quot; полученной последовательности, окончательный результат: 1010000001000&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 16641 = 129 * 129.&lt;br /&gt;
* Этап 5. Вычисление остатка по модулю 2&amp;lt;sup&amp;gt;N&amp;lt;/sup&amp;gt;+1. В данном случае 16641 = 16641 mod 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt;+1&lt;br /&gt;
&lt;br /&gt;
=== Описание ===&lt;br /&gt;
* [http://gmplib.org/manual/FFT-Multiplication.html#FFT-Multiplication Документация GMP LIB]&lt;br /&gt;
* [http://hal.archives-ouvertes.fr/docs/00/12/64/62/PDF/fft.pdf Статья A GMP-BASED IMPLEMENTATION OF SCHONHAGE-STRASSEN’S LARGE INTEGER MULTIPLICATION ALGORITHM]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Sch%C3%B6nhage%E2%80%93Strassen_algorithm Описание в английской Wikipedia]&lt;br /&gt;
&lt;br /&gt;
=== Исходники ===&lt;br /&gt;
[http://www.ginac.de/CLN/cln.git/?p=cln.git;a=blob;f=src/base/digitseq/cl_DS_mul_fftm.h;h=a984802ce039e8179a26fda2681a2e133dba6fbd;hb=refs/heads/master CLN - Class Library for Numbers]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/myachik/ss_mult/blob/master/ss_mult.cpp Вариант реализации алгоритма]&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%A8%D1%91%D0%BD%D1%85%D0%B0%D0%B3%D0%B5_%E2%80%94_%D0%A8%D1%82%D1%80%D0%B0%D1%81%D1%81%D0%B5%D0%BD%D0%B0_(New)</id>
		<title>Метод умножения Шёнхаге — Штрассена (New)</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%A8%D1%91%D0%BD%D1%85%D0%B0%D0%B3%D0%B5_%E2%80%94_%D0%A8%D1%82%D1%80%D0%B0%D1%81%D1%81%D0%B5%D0%BD%D0%B0_(New)"/>
				<updated>2014-01-13T13:12:48Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Шёнхаге - Штрассена''' - асимптотически быстрый алгоритм умножения больших чисел. Он был разработан Арнольдом Шёнхаге и Фолькером Штрассеном в 1971. Сложность алгоритма в нотации &amp;quot;О - большого&amp;quot; составляет O(''N''&amp;amp;nbsp;log&amp;amp;nbsp;''N''&amp;amp;nbsp;log&amp;amp;nbsp;log&amp;amp;nbsp;''N''). Алгоритм&lt;br /&gt;
рекурсивно использует быстрое преобразование Фурье над кольцом из  2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 элементов, специальный тип дискретного преобразования Фурье - теоретико-числовое преобразование.&lt;br /&gt;
&lt;br /&gt;
Алгоритм Шёнхаге - Штрассена являлся наиболее быстрым асимптотически известным методом умножения с 1971 до 2007, когда Фюрером был предложен более быстрый метод. Тем не менее, алгоритм Фюрера в настоящее время имеет преимущество только для астрономически больших чисел и не используется на практике.&lt;br /&gt;
&lt;br /&gt;
На практике алгоритм Шёнхаге - Штрассена начинает превосходить в скорости старые методы, такие как алгоритм Карацубы и алгоритм Тоома-Кука для чисел между 2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;15&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt; и 2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;17&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt; (от 10,000 до 40,000 десятичных разрядов).&lt;br /&gt;
&lt;br /&gt;
Приложения алгоритма Шёнхаге - Штрассена включают в себя как чисто математические задачи, такие как поиск простых чисел Мерсенна и вычисление цифр числа ''π'', так и практические, такие как вычисление подстановки Кронекера, в которой умножение многочленов с целыми коэффициентами можно эффективно заменить умножением больших чисел; это используется на практике by GMP-ECM для факторизации целых чисел методом эллиптических кривых Ленстры.&lt;br /&gt;
&lt;br /&gt;
== Теория ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Свертка ===&lt;br /&gt;
Допустим, что мы перемножаем числа 123 и 456 «в столбик», однако без выполнения переноса. Результат будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|   ||        || 1 || 2 || 3&lt;br /&gt;
|-&lt;br /&gt;
|   || &amp;amp;times;|| 4 || 5 || 6&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   ||        || 6 || 12 || 18&lt;br /&gt;
|-&lt;br /&gt;
|   ||      5 || 10 || 15 ||&lt;br /&gt;
|-&lt;br /&gt;
| 4 ||      8 || 12 ||    ||&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 4 ||     13 || 28 || 27 || 18&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Эта последовательность (4, 13, 28, 27, 18) называется ''ациклической'' или ''линейной свёрткой'' от последовательностей (1,2,3) и (4,5,6). Зная ациклическую свёртку двух последовательностей, рассчитать произведение несложно: достаточно выполнить перенос (например, в самом правом столбце, мы оставляем 8 и добавляем 1 к столбцу, содержащему 27). В нашем примере это приводит к результату 56088.&lt;br /&gt;
&lt;br /&gt;
Есть и другие типы свёрток, которые могут быть полезны. Допустим, что входящие последовательности содержат ''n'' элементов (в примере — 3). Тогда результирующая линейная свёртка содержит ''n'' + ''n'' &amp;amp;minus; 1 элементов; если мы возьмём самый правый столбец ''n'' элементов и добавим самый левый столбец ''n'' &amp;amp;minus; 1 ', в результате мы получим циклическую свёртку:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|   || 28 || 27 || 18&lt;br /&gt;
|-&lt;br /&gt;
| + ||    ||  4 || 13&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   || 28 || 31 || 31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Если мы произведём перенос при циклическом свёртывании, результат будет тот же, что и при произведении чисел по модулю B&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;minus;&amp;amp;nbsp;1 (в данном примере это 10&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;minus;&amp;amp;nbsp;1 = 999). Выполним перенос по (28, 31, 31) и получим 3141, при этом 3141 ≡ 56088 (mod 999).&lt;br /&gt;
&lt;br /&gt;
Наоборот, если мы возьмём самый правый столбец ''n'' элементов и ''вычтем'' самый левый столбец ''n''&amp;amp;minus;1 элементов, то в результате мы получим обратную свёртку:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|         || 28 || 27 || 18&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;minus; ||    ||  4 || 13&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|         || 28 || 23 ||  5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Если мы произведём перенос при обратном свёртывании, то результат будет тот же, что и при произведении чисел по модулю B&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1. В данном примере, 10&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 = 1001, выполним перенос по (28, 23, 5) и получим 3035, при этом 3035 ≡ 56088 (mod 1001). Обратная свёртка может содержать отрицательные числа, которые могут быть убраны во время переноса, используя ту же технику, что и при длинных вычитаниях.&lt;br /&gt;
&lt;br /&gt;
=== Теорема о свёртке ===&lt;br /&gt;
&lt;br /&gt;
Как и другие методы, основанные на быстром преобразовании Фурье, алгоритм Шёнхаге - Штрассена в корне зависит от теоремы о свёртке, которая обеспечивает эффективный способ посчитать циклическую свёртку двух последовательностей. Её идея состоит в следующем:&lt;br /&gt;
&lt;br /&gt;
: Циклическая свёртка двух векторов может быть найдена через [[дискретное преобразование Фурье]] (ДПФ) каждого из них, путём произведения результирующих векторов элемент за элементом, с последующим обратным преобразованием Фурье (ОДПФ).&lt;br /&gt;
&lt;br /&gt;
Или через формулы:&lt;br /&gt;
&lt;br /&gt;
: CyclicConvolution(X, Y) = IDFT(DFT(X) &amp;amp;middot; DFT(Y)), где:&lt;br /&gt;
:: CyclicConvolution — ''циклическая свертка'',&lt;br /&gt;
:: DFT — ''дискретное преобразование Фурье'',&lt;br /&gt;
:: IDFT — ''обратное дискретное преобразование Фурье''.&lt;br /&gt;
&lt;br /&gt;
Если мы посчитаем ДПФ и ОДПФ, используя быстрое преобразование Фурье, и вызовем наш алгоритм перемножения рекурсивно, чтобы перемножить входы(?) преобразованных векторов DFT(X) и DFT(Y), то в результате мы получим эффективный алгоритм для расчёта циклической свёртки.&lt;br /&gt;
&lt;br /&gt;
В этом алгоритме, гораздо эффективней считать ''обратную циклическую'' свёртку; как оказывается, немного модифицированная версия теоремы о свёртке может позволить и это. Предположим, что вектора X и Y имеют длину ''n'', и ''a'' — примитивный корень порядка 2''n'' (это означает, что ''a''&amp;lt;sup&amp;gt;2''n''&amp;lt;/sup&amp;gt; = 1 и все меньшие степени ''a'' не равны 1). Таким образом мы можем определить третий вектор ''A'', называемый ''вектор веса'', обладающий следующими свойствами:&lt;br /&gt;
[[Файл:DIT-FFT-butterfly.png|мини|Операция «[[бабочка (БПФ)|бабочка]]».]]&lt;br /&gt;
&lt;br /&gt;
: ''A'' = (''a''&amp;lt;sup&amp;gt;''j''&amp;lt;/sup&amp;gt;), 0 &amp;amp;le; ''j'' &amp;lt; ''n''&lt;br /&gt;
: ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt; = (''a''&amp;lt;sup&amp;gt;&amp;amp;minus;j''&amp;lt;/sup&amp;gt;), 0 &amp;amp;le; ''j'' &amp;lt; ''n''&lt;br /&gt;
&lt;br /&gt;
Теперь мы можем записать:&lt;br /&gt;
&lt;br /&gt;
: NegacyclicConvolution(''X'', ''Y'') = ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt; &amp;amp;middot; IDFT(DFT(''A'' &amp;amp;middot; ''X'') &amp;amp;middot; DFT(''A'' &amp;amp;middot; ''Y'')), где&lt;br /&gt;
:: NegacyclicConvolution — ''Обратная циклическая свертка'',&lt;br /&gt;
:: DFT — ''дискретное преобразование Фурье'',&lt;br /&gt;
:: IDFT — ''обратное дискретное преобразование Фурье''.&lt;br /&gt;
&lt;br /&gt;
Другими словами, это то же самое за исключением того, что входящие векторы умножены на ''A'', а результат умножен на ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Выбор кольца ===&lt;br /&gt;
&lt;br /&gt;
Дискретное преобразование Фурье — абстрактная операция, которая может быть выполнена в любом алгебраическом [[Кольцо (математика)|кольце]]; обычно оно берётся из поля комплексных чисел, но фактически использовать комплексную арифметику с достаточной точностью, чтобы обеспечить точные результаты, медленно и неэффективно. Вместо этого мы можем использовать теоретико-числовое преобразование, которое производит преобразование в поле целых чисел по модулю N для некоторого целого N.&lt;br /&gt;
&lt;br /&gt;
Так же как есть примитивные корни единицы любого порядка на комплексной плоскости, при любом заданном ''n'' мы можем выбрать подходящее N такое, что ''b'' — примитивный корень единицы порядка ''n'' в поле целых чисел по модулю N (другими словами, ''b''&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt; ≡ 1 (mod N), и все меньшие степени ''b'' не равны 1 mod N).&lt;br /&gt;
&lt;br /&gt;
Алгоритм тратит большую часть времени на рекурсивное выполнение произведения меньших чисел; в простом варианте алгоритма это происходит в ряде мест:&lt;br /&gt;
&lt;br /&gt;
# Внутри алгоритма быстрого преобразования Фурье, примитивный корень единицы ''b'' неоднократно возводится в степень и умножается на другие числа.&lt;br /&gt;
# При возведении в степень примитивного корня единицы ''a'' для получения вектора веса A с последующим умножением векторов A или A&amp;lt;sup&amp;gt;−1&amp;lt;/sup&amp;gt; на другие вектора.&lt;br /&gt;
# При выполнении последовательного перемножения преобразованных векторов.&lt;br /&gt;
&lt;br /&gt;
Ключевой момент — выбрать N, модуль, равный 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 для некоторого целого ''n''. У этого способа есть ряд преимуществ в ряде стандартных систем, в которых большие целые числа представлены в двоичном виде:&lt;br /&gt;
&lt;br /&gt;
* Любое число может быть быстро уменьшено по модулю 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 используя только сдвиг и сложение.&lt;br /&gt;
* Любые примитивные корни единицы в этом кольце могут быть записаны в форме 2&amp;lt;sup&amp;gt;''k''&amp;lt;/sup&amp;gt;; соответственно мы можем умножать или делить любое число на корень из единицы используя сдвиг.&lt;br /&gt;
* Поэлементное рекурсивное перемножение преобразованный векторов может быть выполнено, используя обратную свёртку, которая работает быстрее, чем ациклическая свёртка, и в которой уже есть уменьшение результата &lt;br /&gt;
по модулю 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1.&lt;br /&gt;
&lt;br /&gt;
=== Пример ===&lt;br /&gt;
Следующий пример иллюстрирует работу алгоритма.&lt;br /&gt;
Положим задано два числа: X и Y, каждое длиной 8 бит. Требуется найти значение RES = (X*Y) mod 2&amp;lt;sup&amp;gt;N&amp;lt;/sup&amp;gt;+1&lt;br /&gt;
Возьмём для определённости X = Y = 129&amp;lt;sub&amp;gt;10&amp;lt;/sub&amp;gt; = 1000 0001&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. &lt;br /&gt;
Выберем N = 8 + 8 = 16.&lt;br /&gt;
* Этап 1. Разбиение чисел на K = 4 слов длины M = 4 бита: &lt;br /&gt;
**Дополним числа нулями до длины N = 16 и разобьём на слова. Получим две последовательности (в данном примере идентичные): {0001, 1000, 0000, 0000}. Или в десятичном виде: {3, 8, 0, 0} (слова расположены в порядке от младших бит к старшим). Все операции далее выполняются по модулю 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1, где n выбирается из условия n &amp;gt;= 2*M + log2(K) и является степенью двойки, то есть в нашем случае n &amp;gt;= 2*4 + 2 = 10, n = 16.&lt;br /&gt;
&lt;br /&gt;
* Этап 2. Вычисление свёртки двух последовательностей: &lt;br /&gt;
** Этап 2.1 Умножение последовательностей на весовые коэффициенты. 2K-ый корень из единицы в кольце из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1 элементов равен 2&amp;lt;sup&amp;gt;2n/2K&amp;lt;/sup&amp;gt; = 2&amp;lt;sup&amp;gt;4&amp;lt;/sup&amp;gt; = 16. Результат умножения на вектор весовых коэффициентов в десятичном виде: {1, 128, 0, 0}.&lt;br /&gt;
**Этап 2.2 Прямое преобразование Фурье над кольцом из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. Результат: {129, 32769, 65410, 32770}.&lt;br /&gt;
**Этап 2.3 Покомпонентное произведение последовательностей в кольце из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. Результат: {16641, 49153, 16129, 49155}.&lt;br /&gt;
**Этап 2.4 Обратное преобразование Фурье над кольцом из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. Результат: {1, 256, 16384, 0}.&lt;br /&gt;
**Этап 2.5 Умножение последовательностей на коэффициенты, обратные к используемым в 2.1. Результат: {1, 16, 64, 0}.&lt;br /&gt;
* Этап 3. Выполнение операции переноса. Результат: {1, 0, 1, 4}. В двоичном виде: {0001, 0000, 0001, 0100}&lt;br /&gt;
* Этап 5. &amp;quot;Склейка&amp;quot; полученной последовательности, окончательный результат: 1010000001000&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 16641 = 129 * 129.&lt;br /&gt;
* Этап 5. Вычисление остатка по модулю 2&amp;lt;sup&amp;gt;N&amp;lt;/sup&amp;gt;+1. В данном случае 16641 = 16641 mod 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt;+1&lt;br /&gt;
&lt;br /&gt;
=== Описание ===&lt;br /&gt;
* [http://gmplib.org/manual/FFT-Multiplication.html#FFT-Multiplication Документация GMP LIB]&lt;br /&gt;
* [http://hal.archives-ouvertes.fr/docs/00/12/64/62/PDF/fft.pdf Статья A GMP-BASED IMPLEMENTATION OF SCHONHAGE-STRASSEN’S LARGE INTEGER MULTIPLICATION ALGORITHM]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Sch%C3%B6nhage%E2%80%93Strassen_algorithm Описание в английской Wikipedia]&lt;br /&gt;
&lt;br /&gt;
=== Исходники ===&lt;br /&gt;
[http://www.ginac.de/CLN/cln.git/?p=cln.git;a=blob;f=src/base/digitseq/cl_DS_mul_fftm.h;h=a984802ce039e8179a26fda2681a2e133dba6fbd;hb=refs/heads/master CLN - Class Library for Numbers]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/myachik/ss_mult/blob/master/ss_mult.cpp Вариант реализации алгоритма]&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%A8%D1%91%D0%BD%D1%85%D0%B0%D0%B3%D0%B5_%E2%80%94_%D0%A8%D1%82%D1%80%D0%B0%D1%81%D1%81%D0%B5%D0%BD%D0%B0_(New)</id>
		<title>Метод умножения Шёнхаге — Штрассена (New)</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%A8%D1%91%D0%BD%D1%85%D0%B0%D0%B3%D0%B5_%E2%80%94_%D0%A8%D1%82%D1%80%D0%B0%D1%81%D1%81%D0%B5%D0%BD%D0%B0_(New)"/>
				<updated>2014-01-13T11:31:08Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Шёнхаге - Штрассена''' - асимптотически быстрый алгоритм умножения больших чисел. Он был разработан Арнольдом Шёнхаге и Волкером Штрассеном в 1971. Сложность алгоритма в нотации &amp;quot;О - большого&amp;quot; составляет O(''N''&amp;amp;nbsp;log&amp;amp;nbsp;''N''&amp;amp;nbsp;log&amp;amp;nbsp;log&amp;amp;nbsp;''N''). Алгоритм&lt;br /&gt;
рекурсивно использует быстрое преобразование Фурье над кольцом из  2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 элементов, специальный тип дискретного преобразования Фурье - теоретико-числовое преобразование.&lt;br /&gt;
&lt;br /&gt;
Алгоритм Шёнхаге - Штрассена являлся наиболее быстрым асимптотически известным методом умножения с 1971 до 2007, когда Фюрером был предложен более быстрый метод. Тем не менее, алгоритм Фюрера в настоящее время имеет преимущество только для астрономически больших чисел и не используется на практике.&lt;br /&gt;
&lt;br /&gt;
На практике алгоритм Шёнхаге - Штрассена начинает превосходить в скорости старые методы, такие как алгоритм Карацубы и алгоритм Тоома-Кука для чисел между 2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;15&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt; и 2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;17&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt; (от 10,000 до 40,000 десятичных разрядов).&lt;br /&gt;
&lt;br /&gt;
Приложения алгоритма Шёнхаге - Штрассена включают в себя как чисто математические задачи, такие как поиск простых чисел Мерсенна и вычисление цифр числа ''π'', так и практические, такие как вычисление подстановки Кронекера, в которой умножение многочленов с целыми коэффициентами можно эффективно заменить умножением больших чисел; это используется на практике by GMP-ECM для факторизации целых чисел методом эллиптических кривых Ленстры.&lt;br /&gt;
&lt;br /&gt;
== Теория ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Свертка ===&lt;br /&gt;
Допустим, что мы перемножаем числа 123 и 456 «в столбик», однако без выполнения переноса. Результат будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|   ||        || 1 || 2 || 3&lt;br /&gt;
|-&lt;br /&gt;
|   || &amp;amp;times;|| 4 || 5 || 6&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   ||        || 6 || 12 || 18&lt;br /&gt;
|-&lt;br /&gt;
|   ||      5 || 10 || 15 ||&lt;br /&gt;
|-&lt;br /&gt;
| 4 ||      8 || 12 ||    ||&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 4 ||     13 || 28 || 27 || 18&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Эта последовательность (4, 13, 28, 27, 18) называется ''ациклической'' или ''линейной свёрткой'' от последовательностей (1,2,3) и (4,5,6). Зная ациклическую свёртку двух последовательностей, рассчитать произведение несложно: достаточно выполнить перенос (например, в самом правом столбце, мы оставляем 8 и добавляем 1 к столбцу, содержащему 27). В нашем примере это приводит к результату 56088.&lt;br /&gt;
&lt;br /&gt;
Есть и другие типы свёрток, которые могут быть полезны. Допустим, что входящие последовательности содержат ''n'' элементов (в примере — 3). Тогда результирующая линейная свёртка содержит ''n'' + ''n'' &amp;amp;minus; 1 элементов; если мы возьмём самый правый столбец ''n'' элементов и добавим самый левый столбец ''n'' &amp;amp;minus; 1 ', в результате мы получим циклическую свёртку:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|   || 28 || 27 || 18&lt;br /&gt;
|-&lt;br /&gt;
| + ||    ||  4 || 13&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   || 28 || 31 || 31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Если мы произведём перенос при циклическом свёртывании, результат будет тот же, что и при произведении чисел по модулю B&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;minus;&amp;amp;nbsp;1 (в данном примере это 10&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;minus;&amp;amp;nbsp;1 = 999). Выполним перенос по (28, 31, 31) и получим 3141, при этом 3141 ≡ 56088 (mod 999).&lt;br /&gt;
&lt;br /&gt;
Наоборот, если мы возьмём самый правый столбец ''n'' элементов и ''вычтем'' самый левый столбец ''n''&amp;amp;minus;1 элементов, то в результате мы получим обратную свёртку:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|         || 28 || 27 || 18&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;minus; ||    ||  4 || 13&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|         || 28 || 23 ||  5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Если мы произведём перенос при обратном свёртывании, то результат будет тот же, что и при произведении чисел по модулю B&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1. В данном примере, 10&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 = 1001, выполним перенос по (28, 23, 5) и получим 3035, при этом 3035 ≡ 56088 (mod 1001). Обратная свёртка может содержать отрицательные числа, которые могут быть убраны во время переноса, используя ту же технику, что и при длинных вычитаниях.&lt;br /&gt;
&lt;br /&gt;
=== Теорема о свёртке ===&lt;br /&gt;
&lt;br /&gt;
Как и другие методы, основанные на быстром преобразовании Фурье, алгоритм Шёнхаге - Штрассена в корне зависит от теоремы о свёртке, которая обеспечивает эффективный способ посчитать циклическую свёртку двух последовательностей. Её идея состоит в следующем:&lt;br /&gt;
&lt;br /&gt;
: Циклическая свёртка двух векторов может быть найдена через [[дискретное преобразование Фурье]] (ДПФ) каждого из них, путём произведения результирующих векторов элемент за элементом, с последующим обратным преобразованием Фурье (ОДПФ).&lt;br /&gt;
&lt;br /&gt;
Или через формулы:&lt;br /&gt;
&lt;br /&gt;
: CyclicConvolution(X, Y) = IDFT(DFT(X) &amp;amp;middot; DFT(Y)), где:&lt;br /&gt;
:: CyclicConvolution — ''циклическая свертка'',&lt;br /&gt;
:: DFT — ''дискретное преобразование Фурье'',&lt;br /&gt;
:: IDFT — ''обратное дискретное преобразование Фурье''.&lt;br /&gt;
&lt;br /&gt;
Если мы посчитаем ДПФ и ОДПФ, используя быстрое преобразование Фурье, и вызовем наш алгоритм перемножения рекурсивно, чтобы перемножить входы(?) преобразованных векторов DFT(X) и DFT(Y), то в результате мы получим эффективный алгоритм для расчёта циклической свёртки.&lt;br /&gt;
&lt;br /&gt;
В этом алгоритме, гораздо эффективней считать ''обратную циклическую'' свёртку; как оказывается, немного модифицированная версия теоремы о свёртке может позволить и это. Предположим, что вектора X и Y имеют длину ''n'', и ''a'' — примитивный корень порядка 2''n'' (это означает, что ''a''&amp;lt;sup&amp;gt;2''n''&amp;lt;/sup&amp;gt; = 1 и все меньшие степени ''a'' не равны 1). Таким образом мы можем определить третий вектор ''A'', называемый ''вектор веса'', обладающий следующими свойствами:&lt;br /&gt;
[[Файл:DIT-FFT-butterfly.png|мини|Операция «[[бабочка (БПФ)|бабочка]]».]]&lt;br /&gt;
&lt;br /&gt;
: ''A'' = (''a''&amp;lt;sup&amp;gt;''j''&amp;lt;/sup&amp;gt;), 0 &amp;amp;le; ''j'' &amp;lt; ''n''&lt;br /&gt;
: ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt; = (''a''&amp;lt;sup&amp;gt;&amp;amp;minus;j''&amp;lt;/sup&amp;gt;), 0 &amp;amp;le; ''j'' &amp;lt; ''n''&lt;br /&gt;
&lt;br /&gt;
Теперь мы можем записать:&lt;br /&gt;
&lt;br /&gt;
: NegacyclicConvolution(''X'', ''Y'') = ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt; &amp;amp;middot; IDFT(DFT(''A'' &amp;amp;middot; ''X'') &amp;amp;middot; DFT(''A'' &amp;amp;middot; ''Y'')), где&lt;br /&gt;
:: NegacyclicConvolution — ''Обратная циклическая свертка'',&lt;br /&gt;
:: DFT — ''дискретное преобразование Фурье'',&lt;br /&gt;
:: IDFT — ''обратное дискретное преобразование Фурье''.&lt;br /&gt;
&lt;br /&gt;
Другими словами, это то же самое за исключением того, что входящие векторы умножены на ''A'', а результат умножен на ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Выбор кольца ===&lt;br /&gt;
&lt;br /&gt;
Дискретное преобразование Фурье — абстрактная операция, которая может быть выполнена в любом алгебраическом [[Кольцо (математика)|кольце]]; обычно оно берётся из поля комплексных чисел, но фактически использовать комплексную арифметику с достаточной точностью, чтобы обеспечить точные результаты, медленно и неэффективно. Вместо этого мы можем использовать теоретико-числовое преобразование, которое производит преобразование в поле целых чисел по модулю N для некоторого целого N.&lt;br /&gt;
&lt;br /&gt;
Так же как есть примитивные корни единицы любого порядка на комплексной плоскости, при любом заданном ''n'' мы можем выбрать подходящее N такое, что ''b'' — примитивный корень единицы порядка ''n'' в поле целых чисел по модулю N (другими словами, ''b''&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt; ≡ 1 (mod N), и все меньшие степени ''b'' не равны 1 mod N).&lt;br /&gt;
&lt;br /&gt;
Алгоритм тратит большую часть времени на рекурсивное выполнение произведения меньших чисел; в простом варианте алгоритма это происходит в ряде мест:&lt;br /&gt;
&lt;br /&gt;
# Внутри алгоритма быстрого преобразования Фурье, примитивный корень единицы ''b'' неоднократно возводится в степень и умножается на другие числа.&lt;br /&gt;
# При возведении в степень примитивного корня единицы ''a'' для получения вектора веса A с последующим умножением векторов A или A&amp;lt;sup&amp;gt;−1&amp;lt;/sup&amp;gt; на другие вектора.&lt;br /&gt;
# При выполнении последовательного перемножения преобразованных векторов.&lt;br /&gt;
&lt;br /&gt;
Ключевой момент — выбрать N, модуль, равный 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 для некоторого целого ''n''. У этого способа есть ряд преимуществ в ряде стандартных систем, в которых большие целые числа представлены в двоичном виде:&lt;br /&gt;
&lt;br /&gt;
* Любое число может быть быстро уменьшено по модулю 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 используя только сдвиг и сложение.&lt;br /&gt;
* Любые примитивные корни единицы в этом кольце могут быть записаны в форме 2&amp;lt;sup&amp;gt;''k''&amp;lt;/sup&amp;gt;; соответственно мы можем умножать или делить любое число на корень из единицы используя сдвиг.&lt;br /&gt;
* Поэлементное рекурсивное перемножение преобразованный векторов может быть выполнено, используя обратную свёртку, которая работает быстрее, чем ациклическая свёртка, и в которой уже есть уменьшение результата &lt;br /&gt;
по модулю 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1.&lt;br /&gt;
&lt;br /&gt;
=== Пример ===&lt;br /&gt;
Следующий пример иллюстрирует работу алгоритма.&lt;br /&gt;
Положим задано два числа: X и Y, каждое длиной 8 бит. Требуется найти значение RES = (X*Y) mod 2&amp;lt;sup&amp;gt;N&amp;lt;/sup&amp;gt;+1&lt;br /&gt;
Возьмём для определённости X = Y = 129&amp;lt;sub&amp;gt;10&amp;lt;/sub&amp;gt; = 1000 0001&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. &lt;br /&gt;
Выберем N = 8 + 8 = 16.&lt;br /&gt;
* Этап 1. Разбиение чисел на K = 4 слов длины M = 4 бита: &lt;br /&gt;
**Дополним числа нулями до длины N = 16 и разобьём на слова. Получим две последовательности (в данном примере идентичные): {0001, 1000, 0000, 0000}. Или в десятичном виде: {3, 8, 0, 0} (слова расположены в порядке от младших бит к старшим). Все операции далее выполняются по модулю 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1, где n выбирается из условия n &amp;gt;= 2*M + log2(K) и является степенью двойки, то есть в нашем случае n &amp;gt;= 2*4 + 2 = 10, n = 16.&lt;br /&gt;
&lt;br /&gt;
* Этап 2. Вычисление свёртки двух последовательностей: &lt;br /&gt;
** Этап 2.1 Умножение последовательностей на весовые коэффициенты. 2K-ый корень из единицы в кольце из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1 элементов равен 2&amp;lt;sup&amp;gt;2n/2K&amp;lt;/sup&amp;gt; = 2&amp;lt;sup&amp;gt;4&amp;lt;/sup&amp;gt; = 16. Результат умножения на вектор весовых коэффициентов в десятичном виде: {1, 128, 0, 0}.&lt;br /&gt;
**Этап 2.2 Прямое преобразование Фурье над кольцом из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. Результат: {129, 32769, 65410, 32770}.&lt;br /&gt;
**Этап 2.3 Покомпонентное произведение последовательностей в кольце из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. Результат: {16641, 49153, 16129, 49155}.&lt;br /&gt;
**Этап 2.4 Обратное преобразование Фурье над кольцом из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. Результат: {1, 256, 16384, 0}.&lt;br /&gt;
**Этап 2.5 Умножение последовательностей на коэффициенты, обратные к используемым в 2.1. Результат: {1, 16, 64, 0}.&lt;br /&gt;
* Этап 3. Выполнение операции переноса. Результат: {1, 0, 1, 4}. В двоичном виде: {0001, 0000, 0001, 0100}&lt;br /&gt;
* Этап 5. &amp;quot;Склейка&amp;quot; полученной последовательности, окончательный результат: 1010000001000&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 16641 = 129 * 129.&lt;br /&gt;
* Этап 5. Вычисление остатка по модулю 2&amp;lt;sup&amp;gt;N&amp;lt;/sup&amp;gt;+1. В данном случае 16641 = 16641 mod 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt;+1&lt;br /&gt;
&lt;br /&gt;
=== Описание ===&lt;br /&gt;
* [http://gmplib.org/manual/FFT-Multiplication.html#FFT-Multiplication Документация GMP LIB]&lt;br /&gt;
* [http://hal.archives-ouvertes.fr/docs/00/12/64/62/PDF/fft.pdf Статья A GMP-BASED IMPLEMENTATION OF SCHONHAGE-STRASSEN’S LARGE INTEGER MULTIPLICATION ALGORITHM]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Sch%C3%B6nhage%E2%80%93Strassen_algorithm Описание в английской Wikipedia]&lt;br /&gt;
&lt;br /&gt;
=== Исходники ===&lt;br /&gt;
[http://www.ginac.de/CLN/cln.git/?p=cln.git;a=blob;f=src/base/digitseq/cl_DS_mul_fftm.h;h=a984802ce039e8179a26fda2681a2e133dba6fbd;hb=refs/heads/master CLN - Class Library for Numbers]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/myachik/ss_mult/blob/master/ss_mult.cpp Вариант реализации алгоритма]&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%A8%D1%91%D0%BD%D1%85%D0%B0%D0%B3%D0%B5_%E2%80%94_%D0%A8%D1%82%D1%80%D0%B0%D1%81%D1%81%D0%B5%D0%BD%D0%B0_(New)</id>
		<title>Метод умножения Шёнхаге — Штрассена (New)</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%A8%D1%91%D0%BD%D1%85%D0%B0%D0%B3%D0%B5_%E2%80%94_%D0%A8%D1%82%D1%80%D0%B0%D1%81%D1%81%D0%B5%D0%BD%D0%B0_(New)"/>
				<updated>2014-01-13T11:30:29Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Шёнхаге - Штрассена''' - асимптотически быстрый алгоритм умножения больших чисел. Он был разработан Арнольдом Шёнхаге и Волкером Штрассеном в 1971. Сложность алгоритма в нотации &amp;quot;О - большого&amp;quot; составляет O(''N''&amp;amp;nbsp;log&amp;amp;nbsp;''N''&amp;amp;nbsp;log&amp;amp;nbsp;log&amp;amp;nbsp;''N''). Алгоритм&lt;br /&gt;
рекурсивно использует быстрое преобразование Фурье над кольцом из  2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 элементов, специальный тип дискретного преобразования Фурье - теоретико-числовое преобразование.&lt;br /&gt;
&lt;br /&gt;
Алгоритм Шёнхаге - Штрассена являлся наиболее быстрым асимптотически известным методом умножения с 1971 до 2007, когда Фюрером был предложен более быстрый метод. Тем не менее, алгоритм Фюрера в настоящее время имеет преимущество только для астрономически больших чисел и не используется на практике.&lt;br /&gt;
&lt;br /&gt;
На практике алгоритм Шёнхаге - Штрассена начинает превосходить в скорости старые методы, такие как алгоритм Карацубы и алгоритм Тоома-Кука для чисел между 2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;15&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt; и 2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;17&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt; (от 10,000 до 40,000 десятичных разрядов).&lt;br /&gt;
&lt;br /&gt;
Приложения алгоритма Шёнхаге - Штрассена включают в себя как чисто математические задачи, такие как поиск простых чисел Мерсенна и вычисление цифр числа ''π'', так и практические, такие как вычисление подстановки Кронекера, в которой умножение многочленов с целыми коэффициентами можно эффективно заменить умножением больших чисел; это используется на практике by GMP-ECM для факторизации целых чисел методом эллиптических кривых Ленстры.&lt;br /&gt;
&lt;br /&gt;
== Теория ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Свертка ===&lt;br /&gt;
Допустим, что мы перемножаем числа 123 и 456 «в столбик», однако без выполнения переноса. Результат будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|   ||        || 1 || 2 || 3&lt;br /&gt;
|-&lt;br /&gt;
|   || &amp;amp;times;|| 4 || 5 || 6&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   ||        || 6 || 12 || 18&lt;br /&gt;
|-&lt;br /&gt;
|   ||      5 || 10 || 15 ||&lt;br /&gt;
|-&lt;br /&gt;
| 4 ||      8 || 12 ||    ||&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 4 ||     13 || 28 || 27 || 18&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Эта последовательность (4, 13, 28, 27, 18) называется ''ациклической'' или ''линейной свёрткой'' от последовательностей (1,2,3) и (4,5,6). Зная ациклическую свёртку двух последовательностей, рассчитать произведение несложно: достаточно выполнить перенос (например, в самом правом столбце, мы оставляем 8 и добавляем 1 к столбцу, содержащему 27). В нашем примере это приводит к результату 56088.&lt;br /&gt;
&lt;br /&gt;
Есть и другие типы свёрток, которые могут быть полезны. Допустим, что входящие последовательности содержат ''n'' элементов (в примере — 3). Тогда результирующая линейная свёртка содержит ''n'' + ''n'' &amp;amp;minus; 1 элементов; если мы возьмём самый правый столбец ''n'' элементов и добавим самый левый столбец ''n'' &amp;amp;minus; 1 ', в результате мы получим циклическую свёртку:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|   || 28 || 27 || 18&lt;br /&gt;
|-&lt;br /&gt;
| + ||    ||  4 || 13&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   || 28 || 31 || 31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Если мы произведём перенос при циклическом свёртывании, результат будет тот же, что и при произведении чисел по модулю B&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;minus;&amp;amp;nbsp;1 (в данном примере это 10&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;minus;&amp;amp;nbsp;1 = 999). Выполним перенос по (28, 31, 31) и получим 3141, при этом 3141 ≡ 56088 (mod 999).&lt;br /&gt;
&lt;br /&gt;
Наоборот, если мы возьмём самый правый столбец ''n'' элементов и ''вычтем'' самый левый столбец ''n''&amp;amp;minus;1 элементов, то в результате мы получим обратную свёртку:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|         || 28 || 27 || 18&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;minus; ||    ||  4 || 13&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|         || 28 || 23 ||  5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Если мы произведём перенос при обратном свёртывании, то результат будет тот же, что и при произведении чисел по модулю B&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1. В данном примере, 10&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 = 1001, выполним перенос по (28, 23, 5) и получим 3035, при этом 3035 ≡ 56088 (mod 1001). Обратная свёртка может содержать отрицательные числа, которые могут быть убраны во время переноса, используя ту же технику, что и при длинных вычитаниях.&lt;br /&gt;
&lt;br /&gt;
=== Теорема о свёртке ===&lt;br /&gt;
&lt;br /&gt;
Как и другие методы, основанные на быстром преобразовании Фурье, алгоритм Шёнхаге - Штрассена в корне зависит от теоремы о свёртке, которая обеспечивает эффективный способ посчитать циклическую свёртку двух последовательностей. Её идея состоит в следующем:&lt;br /&gt;
&lt;br /&gt;
: Циклическая свёртка двух векторов может быть найдена через [[дискретное преобразование Фурье]] (ДПФ) каждого из них, путём произведения результирующих векторов элемент за элементом, с последующим обратным преобразованием Фурье (ОДПФ).&lt;br /&gt;
&lt;br /&gt;
Или через формулы:&lt;br /&gt;
&lt;br /&gt;
: CyclicConvolution(X, Y) = IDFT(DFT(X) &amp;amp;middot; DFT(Y)), где:&lt;br /&gt;
:: CyclicConvolution — ''циклическая свертка'',&lt;br /&gt;
:: DFT — ''дискретное преобразование Фурье'',&lt;br /&gt;
:: IDFT — ''обратное дискретное преобразование Фурье''.&lt;br /&gt;
&lt;br /&gt;
Если мы посчитаем ДПФ и ОДПФ, используя быстрое преобразование Фурье, и вызовем наш алгоритм перемножения рекурсивно, чтобы перемножить входы(?) преобразованных векторов DFT(X) и DFT(Y), то в результате мы получим эффективный алгоритм для расчёта циклической свёртки.&lt;br /&gt;
&lt;br /&gt;
В этом алгоритме, гораздо эффективней считать ''обратную циклическую'' свёртку; как оказывается, немного модифицированная версия теоремы о свёртке может позволить и это. Предположим, что вектора X и Y имеют длину ''n'', и ''a'' — примитивный корень порядка 2''n'' (это означает, что ''a''&amp;lt;sup&amp;gt;2''n''&amp;lt;/sup&amp;gt; = 1 и все меньшие степени ''a'' не равны 1). Таким образом мы можем определить третий вектор ''A'', называемый ''вектор веса'', обладающий следующими свойствами:&lt;br /&gt;
[[Файл:DIT-FFT-butterfly.png|мини|Операция «[[бабочка (БПФ)|бабочка]]».]]&lt;br /&gt;
&lt;br /&gt;
: ''A'' = (''a''&amp;lt;sup&amp;gt;''j''&amp;lt;/sup&amp;gt;), 0 &amp;amp;le; ''j'' &amp;lt; ''n''&lt;br /&gt;
: ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt; = (''a''&amp;lt;sup&amp;gt;&amp;amp;minus;j''&amp;lt;/sup&amp;gt;), 0 &amp;amp;le; ''j'' &amp;lt; ''n''&lt;br /&gt;
&lt;br /&gt;
Теперь мы можем записать:&lt;br /&gt;
&lt;br /&gt;
: NegacyclicConvolution(''X'', ''Y'') = ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt; &amp;amp;middot; IDFT(DFT(''A'' &amp;amp;middot; ''X'') &amp;amp;middot; DFT(''A'' &amp;amp;middot; ''Y'')), где&lt;br /&gt;
:: NegacyclicConvolution — ''Обратная циклическая свертка'',&lt;br /&gt;
:: DFT — ''дискретное преобразование Фурье'',&lt;br /&gt;
:: IDFT — ''обратное дискретное преобразование Фурье''.&lt;br /&gt;
&lt;br /&gt;
Другими словами, это то же самое за исключением того, что входящие векторы умножены на ''A'', а результат умножен на ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Выбор кольца ===&lt;br /&gt;
&lt;br /&gt;
Дискретное преобразование Фурье — абстрактная операция, которая может быть выполнена в любом алгебраическом [[Кольцо (математика)|кольце]]; обычно оно берётся из поля комплексных чисел, но фактически использовать комплексную арифметику с достаточной точностью, чтобы обеспечить точные результаты, медленно и неэффективно. Вместо этого мы можем использовать теоретико-числовое преобразование, которое производит преобразование в поле целых чисел по модулю N для некоторого целого N.&lt;br /&gt;
&lt;br /&gt;
Так же как есть примитивные корни единицы любого порядка на комплексной плоскости, при любом заданном ''n'' мы можем выбрать подходящее N такое, что ''b'' — примитивный корень единицы порядка ''n'' в поле целых чисел по модулю N (другими словами, ''b''&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt; ≡ 1 (mod N), и все меньшие степени ''b'' не равны 1 mod N).&lt;br /&gt;
&lt;br /&gt;
Алгоритм тратит большую часть времени на рекурсивное выполнение произведения меньших чисел; в простом варианте алгоритма это происходит в ряде мест:&lt;br /&gt;
&lt;br /&gt;
# Внутри алгоритма быстрого преобразования Фурье, примитивный корень единицы ''b'' неоднократно возводится в степень и умножается на другие числа.&lt;br /&gt;
# При возведении в степень примитивного корня единицы ''a'' для получения вектора веса A с последующим умножением векторов A или A&amp;lt;sup&amp;gt;−1&amp;lt;/sup&amp;gt; на другие вектора.&lt;br /&gt;
# При выполнении последовательного перемножения преобразованных векторов.&lt;br /&gt;
&lt;br /&gt;
Ключевой момент — выбрать N, модуль, равный 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 для некоторого целого ''n''. У этого способа есть ряд преимуществ в ряде стандартных систем, в которых большие целые числа представлены в двоичном виде:&lt;br /&gt;
&lt;br /&gt;
* Любое число может быть быстро уменьшено по модулю 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 используя только сдвиг и сложение.&lt;br /&gt;
* Любые примитивные корни единицы в этом кольце могут быть записаны в форме 2&amp;lt;sup&amp;gt;''k''&amp;lt;/sup&amp;gt;; соответственно мы можем умножать или делить любое число на корень из единицы используя сдвиг.&lt;br /&gt;
* Поэлементное рекурсивное перемножение преобразованный векторов может быть выполнено, используя обратную свёртку, которая работает быстрее, чем ациклическая свёртка, и в которой уже есть уменьшение результата &lt;br /&gt;
по модулю 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1.&lt;br /&gt;
&lt;br /&gt;
=== Пример ===&lt;br /&gt;
Следующий пример иллюстрирует работу алгоритма.&lt;br /&gt;
Положим задано два числа: X и Y, каждое длиной 8 бит. Требуется найти значение RES = (X*Y) mod 2&amp;lt;sup&amp;gt;N&amp;lt;/sup&amp;gt;+1&lt;br /&gt;
Возьмём для определённости X = Y = 129&amp;lt;sub&amp;gt;10&amp;lt;/sub&amp;gt; = 1000 0001&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. &lt;br /&gt;
Выберем N = 8 + 8 = 16.&lt;br /&gt;
* Этап 1. Разбиение чисел на K = 4 слов длины M = 4 бита: &lt;br /&gt;
**Дополним числа нулями до длины N = 16 и разобьём на слова. Получим две последовательности (в данном примере идентичные): {0001, 1000, 0000, 0000}. Или в десятичном виде: {3, 8, 0, 0} (слова расположены в порядке от младших бит к старшим). Все операции далее выполняются по модулю 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1, где n выбирается из условия n &amp;gt;= 2*M + log2(K) и является степенью двойки, то есть в нашем случае n &amp;gt;= 2*4 + 2 = 10, n = 16.&lt;br /&gt;
&lt;br /&gt;
* Этап 2. Вычисление свёртки двух последовательностей: &lt;br /&gt;
** Этап 2.1 Умножение последовательностей на весовые коэффициенты. 2K-ый корень из единицы в кольце из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;+1 элементов равен 2&amp;lt;sup&amp;gt;2n/2K&amp;lt;/sup&amp;gt; = 2&amp;lt;sup&amp;gt;4&amp;lt;/sup&amp;gt; = 16. Результат умножения на вектор весовых коэффициентов в десятичном виде: {1, 128, 0, 0}.&lt;br /&gt;
**Этап 2.2 Прямое преобразование Фурье над кольцом из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. Результат: {129, 32769, 65410, 32770}.&lt;br /&gt;
**Этап 2.3 Покомпонентное произведение последовательностей в кольце из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. Результат: {16641, 49153, 16129, 49155}.&lt;br /&gt;
**Этап 2.4 Обратное преобразование Фурье над кольцом из 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; элементов. Результат: {1, 256, 16384, 0}.&lt;br /&gt;
**Этап 2.5 Умножение последовательностей на коэффициенты, обратные к используемым в 2.1. Результат: {1, 16, 64, 0}.&lt;br /&gt;
* Этап 3. Выполнение операции переноса. Результат: {1, 0, 1, 4}. В двоичном виде: {0001, 0000, 0001, 0100}&lt;br /&gt;
* Этап 5. &amp;quot;Склейка&amp;quot; полученной последовательности, получение результата: 1010000001000&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; = 16641 = 129 * 129.&lt;br /&gt;
* Этап 5. Вычисление остатка по модулю 2&amp;lt;sup&amp;gt;N&amp;lt;/sup&amp;gt;+1. В данном случае 16641 = 16641 mod 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt;+1&lt;br /&gt;
&lt;br /&gt;
=== Описание ===&lt;br /&gt;
* [http://gmplib.org/manual/FFT-Multiplication.html#FFT-Multiplication Документация GMP LIB]&lt;br /&gt;
* [http://hal.archives-ouvertes.fr/docs/00/12/64/62/PDF/fft.pdf Статья A GMP-BASED IMPLEMENTATION OF SCHONHAGE-STRASSEN’S LARGE INTEGER MULTIPLICATION ALGORITHM]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Sch%C3%B6nhage%E2%80%93Strassen_algorithm Описание в английской Wikipedia]&lt;br /&gt;
&lt;br /&gt;
=== Исходники ===&lt;br /&gt;
[http://www.ginac.de/CLN/cln.git/?p=cln.git;a=blob;f=src/base/digitseq/cl_DS_mul_fftm.h;h=a984802ce039e8179a26fda2681a2e133dba6fbd;hb=refs/heads/master CLN - Class Library for Numbers]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/myachik/ss_mult/blob/master/ss_mult.cpp Вариант реализации алгоритма]&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%A8%D1%91%D0%BD%D1%85%D0%B0%D0%B3%D0%B5_%E2%80%94_%D0%A8%D1%82%D1%80%D0%B0%D1%81%D1%81%D0%B5%D0%BD%D0%B0_(New)</id>
		<title>Метод умножения Шёнхаге — Штрассена (New)</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D1%83%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%A8%D1%91%D0%BD%D1%85%D0%B0%D0%B3%D0%B5_%E2%80%94_%D0%A8%D1%82%D1%80%D0%B0%D1%81%D1%81%D0%B5%D0%BD%D0%B0_(New)"/>
				<updated>2014-01-13T09:25:23Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: Новая страница: «'''Алгоритм Шёнхаге - Штрассена''' - асимптотически быстрый алгоритм умножения больших чис…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Алгоритм Шёнхаге - Штрассена''' - асимптотически быстрый алгоритм умножения больших чисел. Он был разработан Арнольдом Шёнхаге и Волкером Штрассеном в 1971. Сложность алгоритма в нотации &amp;quot;О - большого&amp;quot; составляет O(''N''&amp;amp;nbsp;log&amp;amp;nbsp;''N''&amp;amp;nbsp;log&amp;amp;nbsp;log&amp;amp;nbsp;''N''). Алгоритм&lt;br /&gt;
рекурсивно использует быстрое преобразование Фурье над кольцом из  2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 элементов, специальный тип дискретного преобразования Фурье - теоретико-числовое преобразование.&lt;br /&gt;
&lt;br /&gt;
Алгоритм Шёнхаге - Штрассена являлся наиболее быстрым асимптотически известным методом умножения с 1971 до 2007, когда Фюрером был предложен более быстрый метод. Тем не менее, алгоритм Фюрера в настоящее время имеет преимущество только для астрономически больших чисел и не используется на практике.&lt;br /&gt;
&lt;br /&gt;
На практике алгоритм Шёнхаге - Штрассена начинает превосходить в скорости старые методы, такие как алгоритм Карацубы и алгоритм Тоома-Кука для чисел между 2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;15&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt; и 2&amp;lt;sup&amp;gt;2&amp;lt;sup&amp;gt;17&amp;lt;/sup&amp;gt;&amp;lt;/sup&amp;gt; (от 10,000 до 40,000 десятичных разрядов).&lt;br /&gt;
&lt;br /&gt;
== Теория ==&lt;br /&gt;
&lt;br /&gt;
=== Свертка ===&lt;br /&gt;
Допустим, что мы перемножаем числа 123 и 456 «в столбик», однако без выполнения переноса. Результат будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|   ||        || 1 || 2 || 3&lt;br /&gt;
|-&lt;br /&gt;
|   || &amp;amp;times;|| 4 || 5 || 6&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   ||        || 6 || 12 || 18&lt;br /&gt;
|-&lt;br /&gt;
|   ||      5 || 10 || 15 ||&lt;br /&gt;
|-&lt;br /&gt;
| 4 ||      8 || 12 ||    ||&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| 4 ||     13 || 28 || 27 || 18&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Эта последовательность (4, 13, 28, 27, 18) называется ''ациклической'' или ''линейной свёрткой'' от последовательностей (1,2,3) и (4,5,6). Зная ациклическую свёртку двух последовательностей, рассчитать произведение несложно: достаточно выполнить перенос (например, в самом правом столбце, мы оставляем 8 и добавляем 1 к столбцу, содержащему 27). В нашем примере это приводит к результату 56088.&lt;br /&gt;
&lt;br /&gt;
Есть и другие типы свёрток, которые могут быть полезны. Допустим, что входящие последовательности содержат ''n'' элементов (в примере — 3). Тогда результирующая линейная свёртка содержит ''n'' + ''n'' &amp;amp;minus; 1 элементов; если мы возьмём самый правый столбец ''n'' элементов и добавим самый левый стоблец ''n'' &amp;amp;minus; 1 ', в результате мы получим циклическую свёртку:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|   || 28 || 27 || 18&lt;br /&gt;
|-&lt;br /&gt;
| + ||    ||  4 || 13&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|   || 28 || 31 || 31&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Если мы произведём перенос при циклическом свёртывании, результат будет тот же, что и при произведении чисел по модулю B&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;minus;&amp;amp;nbsp;1 (в данном примере это 10&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;&amp;amp;nbsp;&amp;amp;minus;&amp;amp;nbsp;1 = 999). Выполним перенос по (28, 31, 31) и получим 3141, при этом 3141 ≡ 56088 (mod 999).&lt;br /&gt;
&lt;br /&gt;
Наоборот, если мы возьмём самый правый столбец ''n'' элементов и ''вычтем'' самый левый столбец ''n''&amp;amp;minus;1 элементов, то в результате мы получим обратную свёртку:&lt;br /&gt;
&lt;br /&gt;
{|width=300&lt;br /&gt;
|         || 28 || 27 || 18&lt;br /&gt;
|-&lt;br /&gt;
| &amp;amp;minus; ||    ||  4 || 13&lt;br /&gt;
|-&lt;br /&gt;
|colspan=5|&amp;lt;hr /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|         || 28 || 23 ||  5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Если мы произведём перенос при обратном свёртывании, то результат будет тот же, что и при произведении чисел по модулю B&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1. В данном примере, 10&amp;lt;sup&amp;gt;3&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 = 1001, выполним перенос по (28, 23, 5) и получим 3035, при этом 3035 ≡ 56088 (mod 1001). Обратная свёртка может содержать отрицательные числа, которые могут быть убраны во время переноса, используя ту же технику, что и при длинных вычитаниях.&lt;br /&gt;
&lt;br /&gt;
=== Теорема о свёртке ===&lt;br /&gt;
&lt;br /&gt;
Как и другие методы, основанные на быстром преобразовании Фурье, алгоритм Фюрера в корне зависит от теоремы о свёртке, которая обеспечивает эффективный способ посчитать циклическую свёртку двух последовательностей. Её идея состоит в следующем:&lt;br /&gt;
&lt;br /&gt;
: Циклическая свёртка двух векторов может быть найдена через [[дискретное преобразование Фурье]] (ДПФ) каждого из них, путём произведения результирующих векторов элемент за элементом, с последующим обратным преобразованием Фурье (ОДПФ).&lt;br /&gt;
&lt;br /&gt;
Или через формулы:&lt;br /&gt;
&lt;br /&gt;
: CyclicConvolution(X, Y) = IDFT(DFT(X) &amp;amp;middot; DFT(Y)), где:&lt;br /&gt;
:: CyclicConvolution — ''циклическая свертка'',&lt;br /&gt;
:: DFT — ''дискретное преобразование Фурье'',&lt;br /&gt;
:: IDFT — ''обратное дискретное преобразование Фурье''.&lt;br /&gt;
&lt;br /&gt;
Если мы посчитаем ДПФ и ОДПФ, используя быстрое преобразование Фурье, и вызовем наш алгоритм перемножения рекурсивно, чтобы перемножить входы(?) преобразованных векторов DFT(X) и DFT(Y), то в результате мы получим эффективный алгоритм для расчёта циклической свёртки.&lt;br /&gt;
&lt;br /&gt;
В этом алгоритме, гораздо эффективней считать ''обратную циклическую'' свёртку; как оказывается, немного модифицированная версия теоремы о свёртке может позволить и это. Предположим, что вектора X и Y имеют длину ''n'', и ''a'' — примитивный корень порядка 2''n'' (это означает, что ''a''&amp;lt;sup&amp;gt;2''n''&amp;lt;/sup&amp;gt; = 1 и все меньшие степени ''a'' не равны 1). Таким образом мы можем определить третий вектор ''A'', называемый ''вектор веса'', обладающий следующими свойствами:&lt;br /&gt;
[[Файл:DIT-FFT-butterfly.png|мини|Операция «[[бабочка (БПФ)|бабочка]]».]]&lt;br /&gt;
&lt;br /&gt;
: ''A'' = (''a''&amp;lt;sup&amp;gt;''j''&amp;lt;/sup&amp;gt;), 0 &amp;amp;le; ''j'' &amp;lt; ''n''&lt;br /&gt;
: ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt; = (''a''&amp;lt;sup&amp;gt;&amp;amp;minus;j''&amp;lt;/sup&amp;gt;), 0 &amp;amp;le; ''j'' &amp;lt; ''n''&lt;br /&gt;
&lt;br /&gt;
Теперь мы можем записать:&lt;br /&gt;
&lt;br /&gt;
: NegacyclicConvolution(''X'', ''Y'') = ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt; &amp;amp;middot; IDFT(DFT(''A'' &amp;amp;middot; ''X'') &amp;amp;middot; DFT(''A'' &amp;amp;middot; ''Y'')), где&lt;br /&gt;
:: NegacyclicConvolution — ''Обратная циклическая сертка'',&lt;br /&gt;
:: DFT — ''дискретное преобразование Фурье'',&lt;br /&gt;
:: IDFT — ''обратное дискретное преобразование Фурье''.&lt;br /&gt;
&lt;br /&gt;
Другими словами, это то же самое за исключением того, что входящие векторы умножены на ''A'', а результат умножен на ''A''&amp;lt;sup&amp;gt;&amp;amp;minus;1&amp;lt;/sup&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Выбор кольца ===&lt;br /&gt;
&lt;br /&gt;
Дискретное преобразование Фурье — абстрактная операция, которая может быть выполнена в любом алгебраическом [[Кольцо (математика)|кольце]]; обычно оно берётся из поля комплексных чисел, но фактически использовать комплексную арифметику с достаточной точностью, чтобы обеспечить точные результаты, медленно и неэффективно. Вместо этого мы можем использовать теоретико-числовое преобразование, которое производит преобразование в поле целых чисел по модулю N для некоторого целого N.&lt;br /&gt;
&lt;br /&gt;
Так же как есть примитивные корни единицы любого порядка на комплексной плоскости, при любом заданном ''n'' мы можем выбрать подходящее N такое, что ''b'' — примитивный корень единицы порядка ''n'' в поле целых чисел по модулю N (другими словами, ''b''&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt; ≡ 1 (mod N), и все меньшие степени ''b'' не равны 1 mod N).&lt;br /&gt;
&lt;br /&gt;
Алгоритм тратит большую часть времени на рекурсивное выполнение произведения меньших чисел; в простом варианте алгоритма это происходит в ряде мест:&lt;br /&gt;
&lt;br /&gt;
# Внутри алгоритма быстрого преобразования Фурье, примитивный корень единицы ''b'' неоднократно возводится в степень и умножается на другие числа.&lt;br /&gt;
# При возведении в степень примитивного корня единицы ''a'' для получения вектора веса A с последующим умножением векторов A или A&amp;lt;sup&amp;gt;−1&amp;lt;/sup&amp;gt; на другие вектора.&lt;br /&gt;
# При выполнении последовательного перемножения преобразованных векторов.&lt;br /&gt;
&lt;br /&gt;
Ключевой момент — выбрать N, модуль, равный 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 для некоторого целого ''n''. У этого способа есть ряд преимуществ в ряде стандартных систем, в которых большие целые числа представлены в двоичном виде:&lt;br /&gt;
&lt;br /&gt;
* Любое число может быть быстро уменьшено по модулю 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1 используя только сдвиг и сложение.&lt;br /&gt;
* Любые примитивные корни единицы в этом кольце могут быть записаны в форме 2&amp;lt;sup&amp;gt;''k''&amp;lt;/sup&amp;gt;; соответственно мы можем умножать или делить любое число на корень из единицы используя сдвиг.&lt;br /&gt;
* Поэлементное рекурсивное перемножение преобразованный векторов может быть выполнено, используя обратную свёртку, которая работает быстрее, чем ациклическая свёртка, и в которой уже есть уменьшение результата &lt;br /&gt;
по модулю 2&amp;lt;sup&amp;gt;''n''&amp;lt;/sup&amp;gt;&amp;amp;nbsp;+&amp;amp;nbsp;1.&lt;br /&gt;
&lt;br /&gt;
=== Пример ===&lt;br /&gt;
Положим задано два числа: X и Y, каждое длиной 512 бит. Требуется найти значение RES = (X*Y) mod 2&amp;lt;sup&amp;gt;N&amp;lt;/sup&amp;gt;+1&lt;br /&gt;
* Этап 1. Основные параметры алгоритма: &lt;br /&gt;
** len1 = 512&lt;br /&gt;
** len2 = 512&lt;br /&gt;
** N = 1024&lt;br /&gt;
** 2&amp;lt;sup&amp;gt;k&amp;lt;/sup&amp;gt; ~ sqrt(N) = 32, k = 5&lt;br /&gt;
** n &amp;gt;= 2*N/2&amp;lt;sup&amp;gt;k&amp;lt;/sup&amp;gt;+k = (2048/32)+5 = 69. Поскольку n должно делиться на 2&amp;lt;sup&amp;gt;k&amp;lt;/sup&amp;gt;, то можно выбрать n = 128.&lt;br /&gt;
* Этап 2 (возникает на умножении DFT(X)*DFT(Y) mod 2&amp;lt;sup&amp;gt;128&amp;lt;/sup&amp;gt;+1): &lt;br /&gt;
** len1 = 129&lt;br /&gt;
** len2 = 129&lt;br /&gt;
** N = 128&lt;br /&gt;
** 2&amp;lt;sup&amp;gt;k&amp;lt;/sup&amp;gt; ~ (sqrt(N) = 11.3). Выберем k = 4. &lt;br /&gt;
** n &amp;gt;= 2*N/2&amp;lt;sup&amp;gt;k&amp;lt;/sup&amp;gt;+k = (256/16)+4 = 20. Поскольку n должно делиться на 2&amp;lt;sup&amp;gt;k&amp;lt;/sup&amp;gt;, то можно выбрать n = 32.&lt;br /&gt;
* Этап 3 (возникает на умножении DFT(X)*DFT(Y) mod 2&amp;lt;sup&amp;gt;32&amp;lt;/sup&amp;gt;+1): &lt;br /&gt;
** len1 = 33&lt;br /&gt;
** len2 = 33&lt;br /&gt;
это умножение можно делать аппаратно, не углубляюсь в рекурсию.&lt;br /&gt;
&lt;br /&gt;
=== Описание ===&lt;br /&gt;
* [http://gmplib.org/manual/FFT-Multiplication.html#FFT-Multiplication Документация GMP LIB]&lt;br /&gt;
* [http://hal.archives-ouvertes.fr/docs/00/12/64/62/PDF/fft.pdf Статья A GMP-BASED IMPLEMENTATION OF SCHONHAGE-STRASSEN’S LARGE INTEGER MULTIPLICATION ALGORITHM]&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Sch%C3%B6nhage%E2%80%93Strassen_algorithm Описание в английской Wikipedia]&lt;br /&gt;
&lt;br /&gt;
=== Исходники ===&lt;br /&gt;
[http://www.ginac.de/CLN/cln.git/?p=cln.git;a=blob;f=src/base/digitseq/cl_DS_mul_fftm.h;h=a984802ce039e8179a26fda2681a2e133dba6fbd;hb=refs/heads/master CLN - Class Library for Numbers]&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%BA%D0%BE%D1%80%D1%80%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D0%BA_Rajendra_S._Katti</id>
		<title>Схема коррекции ошибок Rajendra S. Katti</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%BA%D0%BE%D1%80%D1%80%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D0%BA_Rajendra_S._Katti"/>
				<updated>2013-07-31T12:53:54Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Введение ==&lt;br /&gt;
Метод, описанный автором, основан на использовании избыточной системы остаточных классов. Недостатки представления чисел в такой системе с целью коррекции ошибок при вычислениях покажем на примере.&lt;br /&gt;
&lt;br /&gt;
Пусть избыточная СОК определяется следующими модулями &amp;lt;math&amp;gt; m_1 = 3, m_2 = 4, m_3 = 5, m_4 = 7&amp;lt;/math&amp;gt;, а динамический диапазон определяется &amp;lt;math&amp;gt;m_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;m_2&amp;lt;/math&amp;gt; и соответственно равен &amp;lt;math&amp;gt;\{0,...,11\}&amp;lt;/math&amp;gt;, а модули &amp;lt;math&amp;gt;m_3, m_4&amp;lt;/math&amp;gt; являются дополнительными и необходимы для проверки на ошибки.&lt;br /&gt;
&lt;br /&gt;
Натуральное число из динамического диапазона может быть восстановлено по любым трём из четырёх остатков по представленным модулям. Например, число &amp;lt;math&amp;gt;x=5=(2,1,0,2)&amp;lt;/math&amp;gt; может быть представлено как &amp;lt;math&amp;gt;(2,1,0)&amp;lt;/math&amp;gt; в системе модулей &amp;lt;math&amp;gt;\{m_1, m_2, m_3\}&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;(2,0,2), (1,0,2)&amp;lt;/math&amp;gt; в системах &amp;lt;math&amp;gt;\{m_1, m_3, m_4\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{m_2, m_3, m_4\}&amp;lt;/math&amp;gt; соответственно. Поэтому, если одна цифра отбрасывается в представлении &amp;lt;math&amp;gt;(2,1,0,2)&amp;lt;/math&amp;gt;, правильный результат восстановления будет получен тогда и только тогда, когда отбрасываемая цифра ошибочна. Итак, обнаружение ошибок и коррекция выполняется следующим образом:&lt;br /&gt;
# Если число лежит вне динамического диапазона - произошла ошибка.&lt;br /&gt;
# Остатки отбрасываются по одному и если в результате одного из отбрасываний полученное число лежит в динамическом диапазоне, то отброшенный остаток является ошибочным.&lt;br /&gt;
# Корректное значение остатка получается расширением полученного на шаге 2 множества модулей, остатки по которым не содержат ошибок.&lt;br /&gt;
&lt;br /&gt;
Такой подход требует много времени и вычислительных ресурсов. Ниже будет предложена новая схема обнаружения и коррекции ошибок на основе СОК.&lt;br /&gt;
&lt;br /&gt;
== Модули, имеющие общие делители ==&lt;br /&gt;
Каждый набор остатков необязательно соответствует числу из динамического диапазона, если модули не являются попарно взаимно простыми. Легко показать, что такое соответствие есть тогда и только тогда, когда равенство&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_i|_k = |r_j|_k&amp;lt;/math&amp;gt;,&lt;br /&gt;
выполняется для любых &amp;lt;math&amp;gt;i, j&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;k = gcd(r_i, r_j)&amp;lt;/math&amp;gt;. Таким образом, ошибочный разряд может быть найден выполнением только простой операции вычисления остатка.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, демонстрирующий, как можно проверить набор остатков на наличие ошибок. Проверим набор &amp;lt;math&amp;gt;(2, 6, 30, 42)&amp;lt;/math&amp;gt; в системе модулей &amp;lt;math&amp;gt;\{4, 15, 36, 48\}&amp;lt;/math&amp;gt;. Наибольшие общие делители всевозможных пар модулей соответственно равны: &amp;lt;math&amp;gt;gcd(4, 15) = 1, gcd(4, 36) = 4, gcd(4, 48) = 4, gcd(15, 36) = 3, gcd(15, 48) = 3, gcd(36, 48) = 12&amp;lt;/math&amp;gt;.&lt;br /&gt;
Используя описанное выше соотношение для проверки, получаем: &amp;lt;math&amp;gt;|2|_4=|30|_4, |2|_4=|42|_4, |6|_3 = |30|_3, |6|_3=|42|_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; |30|_{12}=|42|_{12}&amp;lt;/math&amp;gt;. То есть ошибок нет и число может быть восстановлено с использованием китайской теоремы об остатках (КТО) для модулей, имеющих нетривиальные общие делители.&lt;br /&gt;
&lt;br /&gt;
'''КТО для системы модулей, попарно не взаимно простых'''. Пусть есть представление &amp;lt;math&amp;gt;(r_1, ..., r_n)&amp;lt;/math&amp;gt; натурального числа &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, определяемое системой модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt;. Тогда&lt;br /&gt;
:&amp;lt;math&amp;gt;|x|_M = \left | \sum^{n}_{i=1} {{{\alpha}_i}r_i} \right |&amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt; {\alpha}_i &amp;lt;/math&amp;gt;- число, такое что &amp;lt;math&amp;gt;|{\alpha}_i|_M = 0, |{\alpha}_i|_{\frac{M}{{\mu}_i}} = 1 &amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt; {\mu}_i &amp;lt;/math&amp;gt; - числа, такие что &amp;lt;math&amp;gt; M = \prod^n_{i=1}{{\mu}_i} &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; {\mu}_i &amp;lt;/math&amp;gt; делит &amp;lt;math&amp;gt; m_i &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; M = lcm(m_1, ..., m_n) &amp;lt;/math&amp;gt;. Если для некоторого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; такое &amp;lt;math&amp;gt;{\alpha}_i&amp;lt;/math&amp;gt; не существует, то соответствующее слагаемое в сумме опускается. &lt;br /&gt;
&lt;br /&gt;
Операции над числами остаются корректными и в системе не взаимно простых попарно модулей.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Если в множестве модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt; есть имеющие нетривиальный общий делитель, то каждый набор остатков &amp;lt;math&amp;gt;(r_1, ..., r_n)&amp;lt;/math&amp;gt; необязательно соответствует некоторому числу. Каждый набор, для которого такое соответствие имеет место, будем называть '''кодовым словом'''.&lt;br /&gt;
&lt;br /&gt;
'''Расстоянием''' между двумя представлениями чисел в СОК(кодовыми словами) будем считать количество разрядов, в которых кодовые слова различаются между собой. &lt;br /&gt;
&lt;br /&gt;
'''Кодовым расстоянием''' назовём минимальное расстояние среди всех пар кодовых слов.&lt;br /&gt;
&lt;br /&gt;
Чтобы обнаружить и исправить &amp;lt;math&amp;gt;d-1&amp;lt;/math&amp;gt; или меньше ошибок, необходимо и достаточно, чтобы кодовое расстояние было не меньше &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;. Не более &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; ошибок может быть обнаружено и исправлено тогда и только тогда, когда кодовое расстояние больше, чем &amp;lt;math&amp;gt;(2t+1)&amp;lt;/math&amp;gt;. Если кодовое расстояние больше или равно, чем &amp;lt;math&amp;gt;(t+d+1)&amp;lt;/math&amp;gt;, то любая комбинация из &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; ошибок может быть исправлена и до &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;ошибок могут быть обнаружены. &lt;br /&gt;
Для множества из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; модулей в соответствующей системе могут быть представлены числа &amp;lt;math&amp;gt;(0, ..., M-1)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;M = lcm(m_1, ..., m_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Циклическим числом''' &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt; для каждого модуля &amp;lt;math&amp;gt;m_i&amp;lt;/math&amp;gt; назовём &amp;lt;math&amp;gt;c_i = M/m_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
=== Модули с попарно взаимно простыми циклическими числами ===&lt;br /&gt;
Построим теперь систему модулей с попарно взаимно простыми циклическими числами, которая поможет получит эффективный алгоритм обнаружения и коррекции ошибок. &lt;br /&gt;
&lt;br /&gt;
'''Построение 1'''. &lt;br /&gt;
#Выберем &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; попарно взаимно простых циклических чисел, не равных единице &amp;lt;math&amp;gt;(c_1, ..., c_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
#Получим систему модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt; следующим образом:&lt;br /&gt;
:&amp;lt;math&amp;gt;m_i = \frac{1}{c_i}\prod^n_{k=1}{c_k}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полученные модули обладают двумя свойствами:&lt;br /&gt;
#Наименьшие общие кратны всевозможных пар модулей равны между собой.&lt;br /&gt;
#Наибольшие общие делители всевозможных пар модулей различны.&lt;br /&gt;
&lt;br /&gt;
'''Теорема 1'''. Для построенной системы модулей кодовое расстояние равно &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество модулей.&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обнаружения ошибки ====&lt;br /&gt;
#Если &amp;lt;math&amp;gt;r_i \geqslant m_i&amp;lt;/math&amp;gt;, то произошла ошибка в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-том разряде.&lt;br /&gt;
#Если не выполняется хотя бы одно из следующей системы равенств:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_i|_{k_{ij}}=|r_j|_{k_{ij}}, k_{ij} = gcd(m_i, m_j)&amp;lt;/math&amp;gt;,&lt;br /&gt;
то произошла ошибка.&lt;br /&gt;
&lt;br /&gt;
'''Теорема 2'''. Для системы из четырёх модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4)&amp;lt;/math&amp;gt; ошибка в одном разряде влечёт за собой невыполнением как минимум двух, а как максимум трёх равенств из системы выше. Причём, если ошибка в &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;, то равенства, которые не выполняются, содержат &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм локализации ошибки ====&lt;br /&gt;
Теорема 2 даёт алгоритм локализации ошибки. Ошибочным является разряд, который содержится во всех равенствах, которые не выполняются.&lt;br /&gt;
==== Алгоритм коррекции ошибки ====&lt;br /&gt;
Предложим, что ошибка в &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\bar{r_i}&amp;lt;/math&amp;gt; - правильное значение. Тогда &amp;lt;math&amp;gt;\bar{r_i}&amp;lt;/math&amp;gt; можно найти, решая следующую систему уравнений:&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_i}|_{k_a} = |r_j|_{k_a}, k_a = gcd(m_i, m_j)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_i}|_{k_b} = |r_k|_{k_b}, k_b = gcd(m_i, m_k)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Решение заключается в составлении множеств &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \left \{ f = |r_j|_{k_a}  + k_a k_x : f &amp;lt; m_i, k_x \geq 0 \right \}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \left \{ g = |r_k|_{k_b}  + k_b k_y : g &amp;lt; m_i, k_y \geq 0 \right \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
и поиске пересечения &amp;lt;math&amp;gt;A \cap B&amp;lt;/math&amp;gt;. Можно доказать, что такое пересечение всегда непусто и состоит ровно из одного элемента.&lt;br /&gt;
&lt;br /&gt;
==== Примеры ====&lt;br /&gt;
'''Пример обнаружения одной ошибки.'''&lt;br /&gt;
Воспользуемся Построением 1 для получения системы модулей. Используя попарно взаимно простые циклические числа &amp;lt;math&amp;gt;(c_1, c_2, c_3, c_4)=(2, 3, 5, 7)&amp;lt;/math&amp;gt;, получим систему модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4)=(105, 70, 42, 30)&amp;lt;/math&amp;gt;. Пусть теперь в остаточном представлении &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4)=(30, 60, 30, 0)&amp;lt;/math&amp;gt; содержится одна ошибка. Проверяя совместность представления, найдём, что следующие равенства не выполняются:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{35} = |r_2|_{35}, 35 = gcd(105, 70)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{14} = |r_3k|_{14}, 14 = gcd(70, 42)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;r_2&amp;lt;/math&amp;gt; является общим в этих равенствах, ошибочным является остаток &amp;lt;math&amp;gt;60&amp;lt;/math&amp;gt;. Для того чтобы получить правильное значение, составим множества &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; как было описано выше:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \left \{ f = |r_1|_{35}  + 35 k_x : f &amp;lt; 70, k_x \geq 0 \right \}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \left \{ g = |r_3|_{14}  + 14 k_y : g &amp;lt; 70, k_y \geq 0 \right \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получим:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \left \{ 30, 65 \right \}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \left \{ 2,16,30,44,58\right \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом скорректированное значение &amp;lt;math&amp;gt;\{ \bar {r_2} \}= A \cap B = \{ 30 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необязательно вычислять множество &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; полностью. Так как &amp;lt;math&amp;gt;|r_1|_{35} &amp;gt; 14&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;k_y \geq 2&amp;lt;/math&amp;gt;. Вычисления элементов множеств следует прекратить, как только их пересечение больше не пусто.&lt;br /&gt;
'''Пример обнаружения двух и коррекции одной ошибки.'''&lt;br /&gt;
Для обнаружения двух и коррекции одной ошибки требуется по крайней мере 5 модулей и кодовое расстояние равное 4. Если мы выберем циклические числа &amp;lt;math&amp;gt;(2, 3, 5, 7, 11)&amp;lt;/math&amp;gt; мы получим набор модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4, m_5) = (1155, 770, 462, 330, 210)&amp;lt;/math&amp;gt;. Чтобы проверить, есть ли ошибки в остаточном представлении &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4, r_5)&amp;lt;/math&amp;gt;, нужно выяснить, какие из следующих равенств не выполняются:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{385} = |r_2|_{385}, 385 = gcd(1155, 770)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{231} = |r_3|_{231}, 231 = gcd(1155, 462)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{105} = |r_5|_{105}, 105 = gcd(1155, 210)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{154} = |r_3|_{154}, 154 = gcd(462, 770)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{110} = |r_4|_{110}, 110 = gcd(330, 770)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{70} = |r_5|_{70}, 70 = gcd(210, 770)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_3|_{66} = |r_4|_{66}, 66 = gcd(462, 330)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_3|_{42} = |r_5|_{42}, 42 = gcd(462, 210)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_4|_{30} = |r_5|_{30}, 30 = gcd(330, 210)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Следует отметить, что если три или четыре из равенств выше не выполняются, то обнаружена одна ошибка. Если их пять и больше, то ошибок две. Аналогично предыдущему примеру, можно построить три множества &amp;lt;math&amp;gt;A, B, C&amp;lt;/math&amp;gt;. Исправленное значение ошибочного разряда получим, найдя пересечение этих множеств:&lt;br /&gt;
&amp;lt;math&amp;gt;\{ \bar {r_i} \}= A \cap B \cap C&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Модули с произвольными циклическими числами ===&lt;br /&gt;
Если мы уберём ограничение на взаимную простоту циклических числе, то обнаружение и коррекция ошибки может быть всё ещё осуществлена сокращением динамического диапазона. Следующие теорема и следствие связывают кодовое расстояние и динамический диапазон.&lt;br /&gt;
&lt;br /&gt;
'''Теорема 3'''. Пусть есть множество модулей &amp;lt;math&amp;gt;(m_1, m_2, ..., m_n)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(l_1, l_2, ..., l_a)&amp;lt;/math&amp;gt; - множество наименьших общих кратных всевозможных различных пар модулей, где &amp;lt;math&amp;gt;a = C^2_n&amp;lt;/math&amp;gt;. Тогда, если &amp;lt;math&amp;gt;l = \min{(l_1, l_2, ..., l_a)}&amp;lt;/math&amp;gt;, то кодовое расстояние множества всех представлений чисел &amp;lt;math&amp;gt;\{0, ..., l-1\}&amp;lt;/math&amp;gt; в системе остаточных классов равно &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Следствие'''. Пусть есть множество модулей &amp;lt;math&amp;gt;(m_1, m_2, ..., m_n)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(l_1, l_2, ..., l_a)&amp;lt;/math&amp;gt; - множество наименьших общих кратных всевозможных кортежей из &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; различных модулей, где &amp;lt;math&amp;gt;a = C^i_n&amp;lt;/math&amp;gt;. Тогда, если &amp;lt;math&amp;gt;l = \min{(l_1, l_2, ..., l_a)}&amp;lt;/math&amp;gt;, то кодовое расстояние множества всех представлений чисел &amp;lt;math&amp;gt;\{0, ..., l-1\}&amp;lt;/math&amp;gt; в системе остаточных классов равно &amp;lt;math&amp;gt;n - 1 + i&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее будем предполагать, что ошибочный разряд только один. Из теоремы 3 следует, что для коррекции одной ошибки требуется множество из 4 модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4)&amp;lt;/math&amp;gt;. Пусть &amp;lt;math&amp;gt;l_1, l_2, l_3&amp;lt;/math&amp;gt; - соответственно наименьшее из НОК всех пар, наименьшее из НОК всех троек и НОК всех модулей. Из теоремы 3 и следствия из неё следует, что для множества чисел &amp;lt;math&amp;gt;\{0, ..., l_1-1\}&amp;lt;/math&amp;gt; кодовое расстояние соответствующего множества кодовых слов равно &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;, а для множеств &amp;lt;math&amp;gt;\{0, ..., l_2-1\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{0, ..., l_3-1\}&amp;lt;/math&amp;gt; - не меньше &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; и не меньше &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; соответственно. Разделим множество всех кодовых слов на три подмножества:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \{x : 0 \leq x \leq l_1-1\}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \{x : l_1 \leq x \leq l_2-1\}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;C = \{x : l_2 \leq x \leq l_3-1\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для коррекции одной ошибки необходимо кодовое расстояние, равное трём, то есть все слова из &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; выходят за границы динамического диапазона. Пусть необходимо обнаружить/исправить одну ошибку в остаточном представлении.&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обнаружения ошибки ====&lt;br /&gt;
#Если &amp;lt;math&amp;gt;r_i \geqslant m_i&amp;lt;/math&amp;gt;, то произошла ошибка в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-том разряде.&lt;br /&gt;
#Если остаточное представление не является совместным и слово не лежит в динамическом диапазоне, то произошла ошибка. Для проверки нужно воспользоваться КТО для перевода числа из остаточного представления и проверить, выполняется ли &amp;lt;math&amp;gt;x \leq l_1-1&amp;lt;/math&amp;gt;.&lt;br /&gt;
#Если остаточное представление не является совместным, то произошла ошибка.&lt;br /&gt;
#Если остаточное представление является совместным и лежит в динамическом диапазоне, то ошибок нет.&lt;br /&gt;
==== Алгоритм коррекции ошибки ====&lt;br /&gt;
Начнём описание алгоритма со следующей леммы.&lt;br /&gt;
&lt;br /&gt;
'''Лемма 1'''. Существует и единственно кодовое слово в множестве &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, такое что кодовое расстояние между этим словом и остаточным представлением &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4)&amp;lt;/math&amp;gt; равно &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Опишем теперь коррекцию ошибки для каждого варианта:&lt;br /&gt;
#Кодовое слово за пределами динамического диапазона и совместно.&lt;br /&gt;
#Кодовое слово не совместно.&lt;br /&gt;
&lt;br /&gt;
'''Вариант 1'''. Пусть остаточное представление &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4)&amp;lt;/math&amp;gt; соответствует целому &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;. Так как только один разряд ошибочный, то &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; принадлежит множеству &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. Коррекция выполняется следующим образом:&lt;br /&gt;
#Для всех кортежей из трёх остатков вычислить по КТО соответствующее целое.&lt;br /&gt;
#Если полученное целое принадлежит динамическому диапазону, то ошибка в исключённом разряде.&lt;br /&gt;
#Предположим без потери общности, что ошибочным является &amp;lt;math&amp;gt;r_3&amp;lt;/math&amp;gt;. Найдём правильное значение &amp;lt;math&amp;gt;\bar {r_3}&amp;lt;/math&amp;gt; из следующих уравнений:&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_3}|_{k_a} = |r_1|_{k_a}, k_a = gcd(m_3, m_1)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_3}|_{k_b} = |r_2|_{k_b}, k_b = gcd(m_3, m_2)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_3}|_{k_c} = |r_4|_{k_c}, k_c = gcd(m_3, m_4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Если полученных решений несколько, то согласно Лемме 1 только одно из них принадлежит динамическому диапазону.&lt;br /&gt;
&lt;br /&gt;
'''Вариант 2'''. Пусть кодовое слово &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4)&amp;lt;/math&amp;gt; не является совместным, то есть не выполняется равенство:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_i|_{k_a} = |r_j|_{k_a}, k_a = gcd(m_i, m_j)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Значит ошибочным является либо &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;, либо &amp;lt;math&amp;gt;r_j&amp;lt;/math&amp;gt;. Пусть ошибка в &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;, найдём правильное значение, как в шаге 3 выше. Если для полученных решений, соответствующие целые не лежат в динамическом диапазоне, то ошибка в &amp;lt;math&amp;gt;r_j&amp;lt;/math&amp;gt;, и её можно исправить тем же способом, описанным в шаге 3. &lt;br /&gt;
&lt;br /&gt;
==== Примеры ====&lt;br /&gt;
Определим множество модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4) = (8,6,4,2)&amp;lt;/math&amp;gt;. Все кодовые слова и их целые эквиваленты приведены ниже:&lt;br /&gt;
:&amp;lt;math&amp;gt;(0,0,0,0) = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(1,1,1,1) = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(2,2,2,0) = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(3,3,3,1) = 3&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(4,4,0,0) = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(5,5,1,3) = 5&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(6,0,2,0) = 6&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(7,1,3,1) = 7&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(0,2,0,0) = 8&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(1,3,1,1) = 9&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(2,4,2,0) = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(3,5,3,1) = 11&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(4,0,0,0) = 12&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(5,1,1,1) = 13&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(6,2,2,0) = 14&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(7,3,3,1) = 15&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(0,4,0,0) = 16&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(1,5,1,1) = 17&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(2,0,2,0) = 18&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(3,1,3,1) = 19&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(4,2,0,0) = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(5,3,1,1) = 21&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(6,4,2,0) = 22&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(7,5,3,1) = 23&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Множества &amp;lt;math&amp;gt;A, B, C&amp;lt;/math&amp;gt;, определённые выше, равны &amp;lt;math&amp;gt;A = \{0, ..., 3\}, B = \{4, ..., 7\}, C = \{8, ..., 23\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим теперь несколько примеров обнаружения и коррекции. &lt;br /&gt;
&lt;br /&gt;
'''Пример 1 '''. Остаточное представление &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4) = (2,0,2,0)&amp;lt;/math&amp;gt; является совместным и не принадлежит динамическому диапазону. Четыре кортежа из трёх остатков и соответствующие им целые:&lt;br /&gt;
:&amp;lt;math&amp;gt;(2,0,2) = 18&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(0,2,0) = 6&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(2,0,0) = 18&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(2,2,0) = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Единственное представление, лежащее в &amp;lt;math&amp;gt;\{0, ..., 3\}&amp;lt;/math&amp;gt; -  это &amp;lt;math&amp;gt;(2,2,0)&amp;lt;/math&amp;gt;, следовательно &amp;lt;math&amp;gt;r_2 = 0&amp;lt;/math&amp;gt; является ошибочным. Эта ошибка может быть исправлена, правильное значение можно найти из следующих уравнений:&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_2}|_2 = |r_1|_2 = 0&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_2}|_2 = |r_3|_2 = 0&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_2}|_2 = |r_4|_2 = 0&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;\bar {r_2} \leq 5&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Им удовлетворяют три решения: &amp;lt;math&amp;gt;0, 2, 4&amp;lt;/math&amp;gt;. Правильным является &amp;lt;math&amp;gt; \bar {r_2} = 2&amp;lt;/math&amp;gt;, так оставшиеся два соответствуют представлениям, лежащим вне динамического диапазона. &lt;br /&gt;
&lt;br /&gt;
'''Пример 2 '''. Остаточное представление &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4) = (0,0,0,5)&amp;lt;/math&amp;gt;. Так как &amp;lt;math&amp;gt;r_4 \geq 2&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;r_4&amp;lt;/math&amp;gt; - ошибочный. Найдём правильное значение из следующих уравнений:&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_4}|_2 = |r_1|_2 = 0&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_4}|_2 = |r_2|_2 = 0&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_4}|_2 = |r_3|_2 = 0&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;\bar {r_4} \leq 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем &amp;lt;math&amp;gt;\bar {r_4} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Пример 3 '''. Остаточное представление &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4) = (1,3,3,1)&amp;lt;/math&amp;gt; является несовместным, так как не выполняется следующее равенство:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_4 = |r_3|_4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;r_3&amp;lt;/math&amp;gt; - ошибочный. Тогда скорректированное значение &amp;lt;math&amp;gt;r_3&amp;lt;/math&amp;gt; может быть найдено из следующих уравнений:&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_3}|_4 = |r_1|_4 = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_3}|_2 = |r_2|_2 = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_3}|_2 = |r_4|_2 = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;\bar {r_3} \leq 3&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Решая, находим &amp;lt;math&amp;gt; \bar {r_3} = 1 &amp;lt;/math&amp;gt;. Скорректированное остаточное представление &amp;lt;math&amp;gt;(1,3,1,1) = 9&amp;lt;/math&amp;gt; лежит вне динамического диапазона. Значит, ошибочным является &amp;lt;math&amp;gt;r_1&amp;lt;/math&amp;gt;. Проводя аналогичную процедуру, находим &amp;lt;math&amp;gt;r_1 = 3&amp;lt;/math&amp;gt;. Полученное остаточное представление &amp;lt;math&amp;gt;(3,3,3,1) = 3&amp;lt;/math&amp;gt; лежит в динамическом диапазоне, коррекция завершена. Заметим, что мы пытались обнаружить ошибку в остаточном представлении &amp;lt;math&amp;gt;(1,3,3,1)&amp;lt;/math&amp;gt;, которое имеет кодовое расстояние равное &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; с совместными представлениями &amp;lt;math&amp;gt;(1,3,1,1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(3,3,3,1)&amp;lt;/math&amp;gt;. По Лемме 1 только одно из них лежит в динамическом диапазоне.&lt;br /&gt;
== Литература ==&lt;br /&gt;
Rajendra S. Katti, A New Residue Arithmetic Error Correction Scheme, IEEE Trans. Computers, 1996, том 45, стр. 13-19&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%BA%D0%BE%D1%80%D1%80%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D0%BA_Rajendra_S._Katti</id>
		<title>Схема коррекции ошибок Rajendra S. Katti</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%BA%D0%BE%D1%80%D1%80%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D0%BA_Rajendra_S._Katti"/>
				<updated>2013-07-31T12:34:08Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Введение ==&lt;br /&gt;
Метод, описанный автором, основан на использовании избыточной системы остаточных классов. Недостатки представления чисел в такой системе с целью коррекции ошибок при вычислениях покажем на примере.&lt;br /&gt;
&lt;br /&gt;
Пусть избыточная СОК определяется следующими модулями &amp;lt;math&amp;gt; m_1 = 3, m_2 = 4, m_3 = 5, m_4 = 7&amp;lt;/math&amp;gt;, а динамический диапазон определяется &amp;lt;math&amp;gt;m_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;m_2&amp;lt;/math&amp;gt; и соответственно равен &amp;lt;math&amp;gt;\{0,...,11\}&amp;lt;/math&amp;gt;, а модули &amp;lt;math&amp;gt;m_3, m_4&amp;lt;/math&amp;gt; являются дополнительными и необходимы для проверки на ошибки.&lt;br /&gt;
&lt;br /&gt;
Натуральное число из динамического диапазона может быть восстановлено по любым трём из четырёх остатков по представленным модулям. Например, число &amp;lt;math&amp;gt;x=5=(2,1,0,2)&amp;lt;/math&amp;gt; может быть представлено как &amp;lt;math&amp;gt;(2,1,0)&amp;lt;/math&amp;gt; в системе модулей &amp;lt;math&amp;gt;\{m_1, m_2, m_3\}&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;(2,0,2), (1,0,2)&amp;lt;/math&amp;gt; в системах &amp;lt;math&amp;gt;\{m_1, m_3, m_4\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{m_2, m_3, m_4\}&amp;lt;/math&amp;gt; соответственно. Поэтому, если одна цифра отбрасывается в представлении &amp;lt;math&amp;gt;(2,1,0,2)&amp;lt;/math&amp;gt;, правильный результат восстановления будет получен тогда и только тогда, когда отбрасываемая цифра ошибочна. Итак, обнаружение ошибок и коррекция выполняется следующим образом:&lt;br /&gt;
# Если число лежит вне динамического диапазона - произошла ошибка.&lt;br /&gt;
# Остатки отбрасываются по одному и если в результате одного из отбрасываний полученное число лежит в динамическом диапазоне, то отброшенный остаток является ошибочным.&lt;br /&gt;
# Корректное значение остатка получается расширением полученного на шаге 2 множества модулей, остатки по которым не содержат ошибок.&lt;br /&gt;
&lt;br /&gt;
Такой подход требует много времени и вычислительных ресурсов. Ниже будет предложена новая схема обнаружения и коррекции ошибок на основе СОК.&lt;br /&gt;
&lt;br /&gt;
== Модули, имеющие общие делители ==&lt;br /&gt;
Каждый набор остатков необязательно соответствует числу из динамического диапазона, если модули не являются попарно взаимно простыми. Легко показать, что такое соответствие есть тогда и только тогда, когда равенство&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_i|_k = |r_j|_k&amp;lt;/math&amp;gt;,&lt;br /&gt;
выполняется для любых &amp;lt;math&amp;gt;i, j&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;k = gcd(r_i, r_j)&amp;lt;/math&amp;gt;. Таким образом, ошибочный разряд может быть найден выполнением только простой операции вычисления остатка.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, демонстрирующий, как можно проверить набор остатков на наличие ошибок. Проверим набор &amp;lt;math&amp;gt;(2, 6, 30, 42)&amp;lt;/math&amp;gt; в системе модулей &amp;lt;math&amp;gt;\{4, 15, 36, 48\}&amp;lt;/math&amp;gt;. Наибольшие общие делители всевозможных пар модулей соответственно равны: &amp;lt;math&amp;gt;gcd(4, 15) = 1, gcd(4, 36) = 4, gcd(4, 48) = 4, gcd(15, 36) = 3, gcd(15, 48) = 3, gcd(36, 48) = 12&amp;lt;/math&amp;gt;.&lt;br /&gt;
Используя описанное выше соотношение для проверки, получаем: &amp;lt;math&amp;gt;|2|_4=|30|_4, |2|_4=|42|_4, |6|_3 = |30|_3, |6|_3=|42|_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; |30|_{12}=|42|_{12}&amp;lt;/math&amp;gt;. То есть ошибок нет и число может быть восстановлено с использованием китайской теоремы об остатках (КТО) для модулей, имеющих нетривиальные общие делители.&lt;br /&gt;
&lt;br /&gt;
'''КТО для системы модулей, попарно не взаимно простых'''. Пусть есть представление &amp;lt;math&amp;gt;(r_1, ..., r_n)&amp;lt;/math&amp;gt; натурального числа &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, определяемое системой модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt;. Тогда&lt;br /&gt;
:&amp;lt;math&amp;gt;|x|_M = \left | \sum^{n}_{i=1} {{{\alpha}_i}r_i} \right |&amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt; {\alpha}_i &amp;lt;/math&amp;gt;- число, такое что &amp;lt;math&amp;gt;|{\alpha}_i|_M = 0, |{\alpha}_i|_{\frac{M}{{\mu}_i}} = 1 &amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt; {\mu}_i &amp;lt;/math&amp;gt; - числа, такие что &amp;lt;math&amp;gt; M = \prod^n_{i=1}{{\mu}_i} &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; {\mu}_i &amp;lt;/math&amp;gt; делит &amp;lt;math&amp;gt; m_i &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; M = lcm(m_1, ..., m_n) &amp;lt;/math&amp;gt;. Если для некоторого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; такое &amp;lt;math&amp;gt;{\alpha}_i&amp;lt;/math&amp;gt; не существует, то соответствующее слагаемое в сумме опускается. &lt;br /&gt;
&lt;br /&gt;
Операции над числами остаются корректными и в системе не взаимно простых попарно модулей.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Если в множестве модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt; есть имеющие нетривиальный общий делитель, то каждый набор остатков &amp;lt;math&amp;gt;(r_1, ..., r_n)&amp;lt;/math&amp;gt; необязательно соответствует некоторому числу. Каждый набор, для которого такое соответствие имеет место, будем называть '''кодовым словом'''.&lt;br /&gt;
&lt;br /&gt;
'''Расстоянием''' между двумя представлениями чисел в СОК(кодовыми словами) будем считать количество разрядов, в которых кодовые слова различаются между собой. &lt;br /&gt;
&lt;br /&gt;
'''Кодовым расстоянием''' назовём минимальное расстояние среди всех пар кодовых слов.&lt;br /&gt;
&lt;br /&gt;
Чтобы обнаружить и исправить &amp;lt;math&amp;gt;d-1&amp;lt;/math&amp;gt; или меньше ошибок, необходимо и достаточно, чтобы кодовое расстояние было не меньше &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;. Не более &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; ошибок может быть обнаружено и исправлено тогда и только тогда, когда кодовое расстояние больше, чем &amp;lt;math&amp;gt;(2t+1)&amp;lt;/math&amp;gt;. Если кодовое расстояние больше или равно, чем &amp;lt;math&amp;gt;(t+d+1)&amp;lt;/math&amp;gt;, то любая комбинация из &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; ошибок может быть исправлена и до &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;ошибок могут быть обнаружены. &lt;br /&gt;
Для множества из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; модулей в соответствующей системе могут быть представлены числа &amp;lt;math&amp;gt;(0, ..., M-1)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;M = lcm(m_1, ..., m_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Циклическим числом''' &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt; для каждого модуля &amp;lt;math&amp;gt;m_i&amp;lt;/math&amp;gt; назовём &amp;lt;math&amp;gt;c_i = M/m_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
=== Модули с попарно взаимно простыми циклическими числами ===&lt;br /&gt;
Построим теперь систему модулей с попарно взаимно простыми циклическими числами, которая поможет получит эффективный алгоритм обнаружения и коррекции ошибок. &lt;br /&gt;
&lt;br /&gt;
'''Построение 1'''. &lt;br /&gt;
#Выберем &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; попарно взаимно простых циклических чисел, не равных единице &amp;lt;math&amp;gt;(c_1, ..., c_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
#Получим систему модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt; следующим образом:&lt;br /&gt;
:&amp;lt;math&amp;gt;m_i = \frac{1}{c_i}\prod^n_{k=1}{c_k}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полученные модули обладают двумя свойствами:&lt;br /&gt;
#Наименьшие общие кратны всевозможных пар модулей равны между собой.&lt;br /&gt;
#Наибольшие общие делители всевозможных пар модулей различны.&lt;br /&gt;
&lt;br /&gt;
'''Теорема 1'''. Для построенной системы модулей кодовое расстояние равно &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество модулей.&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обнаружения ошибки ====&lt;br /&gt;
#Если &amp;lt;math&amp;gt;r_i \geqslant m_i&amp;lt;/math&amp;gt;, то произошла ошибка в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-том разряде.&lt;br /&gt;
#Если не выполняется хотя бы одно из следующей системы равенств:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_i|_{k_{ij}}=|r_j|_{k_{ij}}, k_{ij} = gcd(m_i, m_j)&amp;lt;/math&amp;gt;,&lt;br /&gt;
то произошла ошибка.&lt;br /&gt;
&lt;br /&gt;
'''Теорема 2'''. Для системы из четырёх модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4)&amp;lt;/math&amp;gt; ошибка в одном разряде влечёт за собой невыполнением как минимум двух, а как максимум трёх равенств из системы выше. Причём, если ошибка в &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;, то равенства, которые не выполняются, содержат &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм локализации ошибки ====&lt;br /&gt;
Теорема 2 даёт алгоритм локализации ошибки. Ошибочным является разряд, который содержится во всех равенствах, которые не выполняются.&lt;br /&gt;
==== Алгоритм коррекции ошибки ====&lt;br /&gt;
Предложим, что ошибка в &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\bar{r_i}&amp;lt;/math&amp;gt; - правильное значение. Тогда &amp;lt;math&amp;gt;\bar{r_i}&amp;lt;/math&amp;gt; можно найти, решая следующую систему уравнений:&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_i}|_{k_a} = |r_j|_{k_a}, k_a = gcd(m_i, m_j)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_i}|_{k_b} = |r_k|_{k_b}, k_b = gcd(m_i, m_k)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Решение заключается в составлении множеств &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \left \{ f = |r_j|_{k_a}  + k_a k_x : f &amp;lt; m_i, k_x \geq 0 \right \}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \left \{ g = |r_k|_{k_b}  + k_b k_y : g &amp;lt; m_i, k_y \geq 0 \right \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
и поиске пересечения &amp;lt;math&amp;gt;A \cap B&amp;lt;/math&amp;gt;. Можно доказать, что такое пересечение всегда непусто и состоит ровно из одного элемента.&lt;br /&gt;
&lt;br /&gt;
==== Примеры ====&lt;br /&gt;
'''Пример обнаружения одной ошибки.'''&lt;br /&gt;
Воспользуемся Построением 1 для получения системы модулей. Используя попарно взаимно простые циклические числа &amp;lt;math&amp;gt;(c_1, c_2, c_3, c_4)=(2, 3, 5, 7)&amp;lt;/math&amp;gt;, получим систему модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4)=(105, 70, 42, 30)&amp;lt;/math&amp;gt;. Пусть теперь в остаточном представлении &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4)=(30, 60, 30, 0)&amp;lt;/math&amp;gt; содержится одна ошибка. Проверяя совместность представления, найдём, что следующие равенства не выполняются:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{35} = |r_2|_{35}, 35 = gcd(105, 70)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{14} = |r_3k|_{14}, 14 = gcd(70, 42)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;r_2&amp;lt;/math&amp;gt; является общим в этих равенствах, ошибочным является остаток &amp;lt;math&amp;gt;60&amp;lt;/math&amp;gt;. Для того чтобы получить правильное значение, составим множества &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; как было описано выше:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \left \{ f = |r_1|_{35}  + 35 k_x : f &amp;lt; 70, k_x \geq 0 \right \}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \left \{ g = |r_3|_{14}  + 14 k_y : g &amp;lt; 70, k_y \geq 0 \right \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получим:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \left \{ 30, 65 \right \}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \left \{ 2,16,30,44,58\right \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом скорректированное значение &amp;lt;math&amp;gt;\{ \bar {r_2} \}= A \cap B = \{ 30 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необязательно вычислять множество &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; полностью. Так как &amp;lt;math&amp;gt;|r_1|_{35} &amp;gt; 14&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;k_y \geq 2&amp;lt;/math&amp;gt;. Вычисления элементов множеств следует прекратить, как только их пересечение больше не пусто.&lt;br /&gt;
'''Пример обнаружения двух и коррекции одной ошибки.'''&lt;br /&gt;
Для обнаружения двух и коррекции одной ошибки требуется по крайней мере 5 модулей и кодовое расстояние равное 4. Если мы выберем циклические числа &amp;lt;math&amp;gt;(2, 3, 5, 7, 11)&amp;lt;/math&amp;gt; мы получим набор модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4, m_5) = (1155, 770, 462, 330, 210)&amp;lt;/math&amp;gt;. Чтобы проверить, есть ли ошибки в остаточном представлении &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4, r_5)&amp;lt;/math&amp;gt;, нужно выяснить, какие из следующих равенств не выполняются:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{385} = |r_2|_{385}, 385 = gcd(1155, 770)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{231} = |r_3|_{231}, 231 = gcd(1155, 462)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{105} = |r_5|_{105}, 105 = gcd(1155, 210)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{154} = |r_3|_{154}, 154 = gcd(462, 770)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{110} = |r_4|_{110}, 110 = gcd(330, 770)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{70} = |r_5|_{70}, 70 = gcd(210, 770)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_3|_{66} = |r_4|_{66}, 66 = gcd(462, 330)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_3|_{42} = |r_5|_{42}, 42 = gcd(462, 210)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_4|_{30} = |r_5|_{30}, 30 = gcd(330, 210)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Следует отметить, что если три или четыре из равенств выше не выполняются, то обнаружена одна ошибка. Если их пять и больше, то ошибок две. Аналогично предыдущему примеру, можно построить три множества &amp;lt;math&amp;gt;A, B, C&amp;lt;/math&amp;gt;. Исправленное значение ошибочного разряда получим, найдя пересечение этих множеств:&lt;br /&gt;
&amp;lt;math&amp;gt;\{ \bar {r_i} \}= A \cap B \cap C&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Модули с произвольными циклическими числами ===&lt;br /&gt;
Если мы уберём ограничение на взаимную простоту циклических числе, то обнаружение и коррекция ошибки может быть всё ещё осуществлена сокращением динамического диапазона. Следующие теорема и следствие связывают кодовое расстояние и динамический диапазон.&lt;br /&gt;
&lt;br /&gt;
'''Теорема 3'''. Пусть есть множество модулей &amp;lt;math&amp;gt;(m_1, m_2, ..., m_n)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(l_1, l_2, ..., l_a)&amp;lt;/math&amp;gt; - множество наименьших общих кратных всевозможных различных пар модулей, где &amp;lt;math&amp;gt;a = C^2_n&amp;lt;/math&amp;gt;. Тогда, если &amp;lt;math&amp;gt;l = \min{(l_1, l_2, ..., l_a)}&amp;lt;/math&amp;gt;, то кодовое расстояние множества всех представлений чисел &amp;lt;math&amp;gt;\{0, ..., l-1\}&amp;lt;/math&amp;gt; в системе остаточных классов равно &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Следствие'''. Пусть есть множество модулей &amp;lt;math&amp;gt;(m_1, m_2, ..., m_n)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(l_1, l_2, ..., l_a)&amp;lt;/math&amp;gt; - множество наименьших общих кратных всевозможных кортежей из &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; различных модулей, где &amp;lt;math&amp;gt;a = C^i_n&amp;lt;/math&amp;gt;. Тогда, если &amp;lt;math&amp;gt;l = \min{(l_1, l_2, ..., l_a)}&amp;lt;/math&amp;gt;, то кодовое расстояние множества всех представлений чисел &amp;lt;math&amp;gt;\{0, ..., l-1\}&amp;lt;/math&amp;gt; в системе остаточных классов равно &amp;lt;math&amp;gt;n - 1 + i&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее будем предполагать, что ошибочный разряд только один. Из теоремы 3 следует, что для коррекции одной ошибки требуется множество из 4 модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4)&amp;lt;/math&amp;gt;. Пусть &amp;lt;math&amp;gt;l_1, l_2, l_3&amp;lt;/math&amp;gt; - соответственно наименьшее из НОК всех пар, наименьшее из НОК всех троек и НОК всех модулей. Из теоремы 3 и следствия из неё следует, что для множества чисел &amp;lt;math&amp;gt;\{0, ..., l_1-1\}&amp;lt;/math&amp;gt; кодовое расстояние соответствующего множества кодовых слов равно &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;, а для множеств &amp;lt;math&amp;gt;\{0, ..., l_2-1\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{0, ..., l_3-1\}&amp;lt;/math&amp;gt; - не меньше &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; и не меньше &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; соответственно. Разделим множество всех кодовых слов на три подмножества:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \{x : 0 \leq x \leq l_1-1\}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \{x : l_1 \leq x \leq l_2-1\}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;C = \{x : l_2 \leq x \leq l_3-1\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для коррекции одной ошибки необходимо кодовое расстояние, равное трём, то есть все слова из &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; выходят за границы динамического диапазона. Пусть необходимо обнаружить/исправить одну ошибку в остаточном представлении.&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обнаружения ошибки ====&lt;br /&gt;
#Если &amp;lt;math&amp;gt;r_i \geqslant m_i&amp;lt;/math&amp;gt;, то произошла ошибка в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-том разряде.&lt;br /&gt;
#Если остаточное представление не является совместным и слово не лежит в динамическом диапазоне, то произошла ошибка. Для проверки нужно воспользоваться КТО для перевода числа из остаточного представления и проверить, выполняется ли &amp;lt;math&amp;gt;x \leq l_1-1&amp;lt;/math&amp;gt;.&lt;br /&gt;
#Если остаточное представление не является совместным, то произошла ошибка.&lt;br /&gt;
#Если остаточное представление является совместным и лежит в динамическом диапазоне, то ошибок нет.&lt;br /&gt;
==== Алгоритм коррекции ошибки ====&lt;br /&gt;
Начнём описание алгоритма со следующей леммы.&lt;br /&gt;
&lt;br /&gt;
'''Лемма 1'''. Существует и единственно кодовое слово в множестве &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;, такое что кодовое расстояние между этим словом и остаточным представлением &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4)&amp;lt;/math&amp;gt; равно &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Опишем теперь коррекцию ошибки для каждого варианта:&lt;br /&gt;
#Кодовое слово за пределами динамического диапазона и совместно.&lt;br /&gt;
#Кодовое слово не совместно.&lt;br /&gt;
&lt;br /&gt;
'''Вариант 1'''. Пусть остаточное представление &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4)&amp;lt;/math&amp;gt; соответствует целому &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;. Так как только один разряд ошибочный, то &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; принадлежит множеству &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. Коррекция выполняется следующим образом:&lt;br /&gt;
#Для всех кортежей из трёх остатков вычислить по КТО соответствующее целое.&lt;br /&gt;
#Если полученное целое принадлежит динамическому диапазону, то ошибка в исключённом разряде.&lt;br /&gt;
#Предположим без потери общности, что ошибочным является &amp;lt;math&amp;gt;r_3&amp;lt;/math&amp;gt;. Найдём правильное значение &amp;lt;math&amp;gt;\bar {r_3}&amp;lt;/math&amp;gt; из следующих уравнений:&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_3}|_{k_a} = |r_1|_{k_a}, k_a = gcd(m_3, m_1)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_3}|_{k_b} = |r_2|_{k_b}, k_b = gcd(m_3, m_2)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_3}|_{k_c} = |r_4|_{k_c}, k_c = gcd(m_3, m_4)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Если полученных решений несколько, то согласно Лемме 1 только одно из них принадлежит динамическому диапазону.&lt;br /&gt;
&lt;br /&gt;
'''Вариант 2'''. Пусть кодовое слово &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4)&amp;lt;/math&amp;gt; не является совместным, то есть не выполняется равенство:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_i|_{k_a} = |r_j|_{k_a}, k_a = gcd(m_i, m_j)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Значит ошибочным является либо &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;, либо &amp;lt;math&amp;gt;r_j&amp;lt;/math&amp;gt;. Пусть ошибка в &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;, найдём правильное значение, как в шаге 3 выше. Если для полученных решений, соответствующие целые не лежат в динамическом диапазоне, то ошибка в &amp;lt;math&amp;gt;r_j&amp;lt;/math&amp;gt;, и её можно исправить тем же способом, описанным в шаге 3. &lt;br /&gt;
&lt;br /&gt;
==== Примеры ====&lt;br /&gt;
Определим множество модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4) = (8,6,4,2)&amp;lt;/math&amp;gt;. Все кодовые слова и их целые эквиваленты приведены ниже:&lt;br /&gt;
:&amp;lt;math&amp;gt;(0,0,0,0) = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(1,1,1,1) = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(2,2,2,0) = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(3,3,3,1) = 3&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(4,4,0,0) = 4&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(5,5,1,3) = 5&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(6,0,2,0) = 6&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(7,1,3,1) = 7&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(0,2,0,0) = 8&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(1,3,1,1) = 9&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(2,4,2,0) = 10&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(3,5,3,1) = 11&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(4,0,0,0) = 12&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(5,1,1,1) = 13&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(6,2,2,0) = 14&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(7,3,3,1) = 15&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(0,4,0,0) = 16&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(1,5,1,1) = 17&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(2,0,2,0) = 18&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(3,1,3,1) = 19&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(4,2,0,0) = 20&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(5,3,1,1) = 21&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(6,4,2,0) = 22&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(7,5,3,1) = 23&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Множества &amp;lt;math&amp;gt;A, B, C&amp;lt;/math&amp;gt;, определённые выше, равны &amp;lt;math&amp;gt;A = \{0, ..., 3\}, B = \{4, ..., 7\}, C = \{8, ..., 23\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим теперь несколько примеров обнаружения и коррекции. &lt;br /&gt;
&lt;br /&gt;
'''Пример 1 '''. Остаточное представление &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4) = (2,0,2,0)&amp;lt;/math&amp;gt; является совместным и не принадлежит динамическому диапазону. Четыре кортежа из трёх остатков и соответствующие им целые:&lt;br /&gt;
:&amp;lt;math&amp;gt;(2,0,2) = 18&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(0,2,0) = 6&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(2,0,0) = 18&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;(2,2,0) = 2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Единственное представление, лежащее в &amp;lt;math&amp;gt;\{0, ..., 3\}&amp;lt;/math&amp;gt; -  это &amp;lt;math&amp;gt;(2,2,0)&amp;lt;/math&amp;gt;, следовательно &amp;lt;math&amp;gt;r_2 = 0&amp;lt;/math&amp;gt; является ошибочным. Эта ошибка может быть исправлена, правильное значение можно найти из следующих уравнений:&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_2}|_2 = |r_1|_2 = 0&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_2}|_2 = |r_3|_2 = 0&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_2}|_2 = |r_4|_2 = 0&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;\bar {r_2} \leq 5&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Им удовлетворяют три решения: &amp;lt;math&amp;gt;0, 2, 4&amp;lt;/math&amp;gt;. Правильным является &amp;lt;math&amp;gt; \bar {r_2} = 2&amp;lt;/math&amp;gt;, так оставшиеся два соответствуют представлениям, лежащим вне динамического диапазона. &lt;br /&gt;
&lt;br /&gt;
'''Пример 2 '''. Остаточное представление &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4) = (0,0,0,5)&amp;lt;/math&amp;gt;. Так как &amp;lt;math&amp;gt;r_4 \geq 2&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;r_4&amp;lt;/math&amp;gt; - ошибочный. Найдём правильное значение из следующих уравнений:&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_4}|_2 = |r_1|_2 = 0&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_4}|_2 = |r_2|_2 = 0&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_4}|_2 = |r_3|_2 = 0&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;\bar {r_4} \leq 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем &amp;lt;math&amp;gt;\bar {r_4} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Пример 3 '''. Остаточное представление &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4) = (1,3,3,1)&amp;lt;/math&amp;gt; является несовместным, так как не выполняется следующее равенство:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_4 = |r_3|_4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;r_3&amp;lt;/math&amp;gt; - ошибочный. Тогда скорректированное значение &amp;lt;math&amp;gt;r_3&amp;lt;/math&amp;gt; может быть найдено из следующих уравнений:&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_3}|_4 = |r_1|_4 = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_3}|_2 = |r_2|_2 = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar {r_3}|_2 = |r_4|_2 = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;\bar {r_3} \leq 3&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Решая, находим &amp;lt;math&amp;gt; \bar {r_3} = 1 &amp;lt;/math&amp;gt;. Скорректированное остаточное представление &amp;lt;math&amp;gt;(1,3,1,1) = 9&amp;lt;/math&amp;gt; лежит вне динамического диапазона. Значит, ошибочным является &amp;lt;math&amp;gt;r_1&amp;lt;/math&amp;gt;. Проводя аналогичную процедуру, находим &amp;lt;math&amp;gt;r_1 = 3&amp;lt;/math&amp;gt;. Полученное остаточное представление &amp;lt;math&amp;gt;(3,3,3,1) = 3&amp;lt;/math&amp;gt; лежит в динамическом диапазоне, коррекция завершена. Заметим, что мы пытались обнаружить ошибку в остаточном представлении &amp;lt;math&amp;gt;(1,3,3,1)&amp;lt;/math&amp;gt;, которое имеет кодовое расстояние равное &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; с совместными представлениями &amp;lt;math&amp;gt;(1,3,1,1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(3,3,3,1)&amp;lt;/math&amp;gt;. По Лемме 1 только одно из них лежит в динамическом диапазоне.&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%BA%D0%BE%D1%80%D1%80%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D0%BA_Rajendra_S._Katti</id>
		<title>Схема коррекции ошибок Rajendra S. Katti</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%BA%D0%BE%D1%80%D1%80%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D0%BA_Rajendra_S._Katti"/>
				<updated>2013-07-31T10:50:13Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Введение ==&lt;br /&gt;
Метод, описанный автором, основан на использовании избыточной системы остаточных классов. Недостатки представления чисел в такой системе с целью коррекции ошибок при вычислениях покажем на примере.&lt;br /&gt;
&lt;br /&gt;
Пусть избыточная СОК определяется следующими модулями &amp;lt;math&amp;gt; m_1 = 3, m_2 = 4, m_3 = 5, m_4 = 7&amp;lt;/math&amp;gt;, а динамический диапазон определяется &amp;lt;math&amp;gt;m_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;m_2&amp;lt;/math&amp;gt; и соответственно равен &amp;lt;math&amp;gt;\{0,...,11\}&amp;lt;/math&amp;gt;, а модули &amp;lt;math&amp;gt;m_3, m_4&amp;lt;/math&amp;gt; являются дополнительными и необходимы для проверки на ошибки.&lt;br /&gt;
&lt;br /&gt;
Натуральное число из динамического диапазона может быть восстановлено по любым трём из четырёх остатков по представленным модулям. Например, число &amp;lt;math&amp;gt;x=5=(2,1,0,2)&amp;lt;/math&amp;gt; может быть представлено как &amp;lt;math&amp;gt;(2,1,0)&amp;lt;/math&amp;gt; в системе модулей &amp;lt;math&amp;gt;\{m_1, m_2, m_3\}&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;(2,0,2), (1,0,2)&amp;lt;/math&amp;gt; в системах &amp;lt;math&amp;gt;\{m_1, m_3, m_4\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{m_2, m_3, m_4\}&amp;lt;/math&amp;gt; соответственно. Поэтому, если одна цифра отбрасывается в представлении &amp;lt;math&amp;gt;(2,1,0,2)&amp;lt;/math&amp;gt;, правильный результат восстановления будет получен тогда и только тогда, когда отбрасываемая цифра ошибочна. Итак, обнаружение ошибок и коррекция выполняется следующим образом:&lt;br /&gt;
# Если число лежит вне динамического диапазона - произошла ошибка.&lt;br /&gt;
# Остатки отбрасываются по одному и если в результате одного из отбрасываний полученное число лежит в динамическом диапазоне, то отброшенный остаток является ошибочным.&lt;br /&gt;
# Корректное значение остатка получается расширением полученного на шаге 2 множества модулей, остатки по которым не содержат ошибок.&lt;br /&gt;
&lt;br /&gt;
Такой подход требует много времени и вычислительных ресурсов. Ниже будет предложена новая схема обнаружения и коррекции ошибок на основе СОК.&lt;br /&gt;
&lt;br /&gt;
== Модули, имеющие общие делители ==&lt;br /&gt;
Каждый набор остатков необязательно соответствует числу из динамического диапазона, если модули не являются попарно взаимно простыми. Легко показать, что такое соответствие есть тогда и только тогда, когда&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_i|_k = |r_j|_k&amp;lt;/math&amp;gt;,&lt;br /&gt;
выполняется для любых &amp;lt;math&amp;gt;i, j&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;k = gcd(r_i, r_j)&amp;lt;/math&amp;gt;. Таким образом, ошибочный разряд может быть найден выполнением только простой операции вычисления остатка.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, демонстрирующий, как можно проверить набор остатков на наличие ошибок. Проверим набор &amp;lt;math&amp;gt;(2, 6, 30, 42)&amp;lt;/math&amp;gt; в системе модулей &amp;lt;math&amp;gt;\{4, 15, 36, 48\}&amp;lt;/math&amp;gt;. Наибольшие общие делители всевозможных пар модулей соответственно равны: &amp;lt;math&amp;gt;gcd(4, 15) = 1, gcd(4, 36) = 4, gcd(4, 48) = 4, gcd(15, 36) = 3, gcd(15, 48) = 3, gcd(36, 48) = 12&amp;lt;/math&amp;gt;.&lt;br /&gt;
Используя описанное выше соотношение для проверки, получаем: &amp;lt;math&amp;gt;|2|_4=|30|_4, |2|_4=|42|_4, |6|_3 = |30|_3, |6|_3=|42|_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; |30|_{12}=|42|_{12}&amp;lt;/math&amp;gt;. То есть ошибок нет и число может быть восстановлено с использованием китайской теоремы об остатках (КТО) для модулей, имеющих нетривиальные общие делители.&lt;br /&gt;
&lt;br /&gt;
'''КТО для системы модулей, попарно не взаимно простых'''. Пусть есть представление &amp;lt;math&amp;gt;(r_1, ..., r_n)&amp;lt;/math&amp;gt; натурального числа &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, определяемое системой модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt;. Тогда&lt;br /&gt;
:&amp;lt;math&amp;gt;|x|_M = \left | \sum^{n}_{i=1} {{{\alpha}_i}r_i} \right |&amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt; {\alpha}_i &amp;lt;/math&amp;gt;- число, такое что &amp;lt;math&amp;gt;|{\alpha}_i|_M = 0, |{\alpha}_i|_{\frac{M}{{\mu}_i}} = 1 &amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt; {\mu}_i &amp;lt;/math&amp;gt; - числа, такие что &amp;lt;math&amp;gt; M = \prod^n_{i=1}{{\mu}_i} &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; {\mu}_i &amp;lt;/math&amp;gt; делит &amp;lt;math&amp;gt; m_i &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; M = lcm(m_1, ..., m_n) &amp;lt;/math&amp;gt;. Если для некоторого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; такое &amp;lt;math&amp;gt;{\alpha}_i&amp;lt;/math&amp;gt; не существует, то соответствующее слагаемое в сумме опускается. &lt;br /&gt;
&lt;br /&gt;
Операции над числами остаются корректными и в системе не взаимно простых попарно модулей.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Если в множестве модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt; есть имеющие нетривиальный общий делитель, то каждый набор остатков &amp;lt;math&amp;gt;(r_1, ..., r_n)&amp;lt;/math&amp;gt; необязательно соответствует некоторому числу. Каждый набор, для которого такое соответствие имеет место, будем называть '''кодовым словом'''.&lt;br /&gt;
&lt;br /&gt;
'''Расстоянием''' между двумя представлениями чисел в СОК(кодовыми словами) будем считать количество разрядов, в которых кодовые слова различаются между собой. &lt;br /&gt;
&lt;br /&gt;
'''Кодовым расстоянием''' назовём минимальное расстояние среди всех пар кодовых слов.&lt;br /&gt;
&lt;br /&gt;
Чтобы обнаружить и исправить &amp;lt;math&amp;gt;d-1&amp;lt;/math&amp;gt; или меньше ошибок, необходимо и достаточно, чтобы кодовое расстояние было не меньше &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;. Не более &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; ошибок может быть обнаружено и исправлено тогда и только тогда, когда кодовое расстояние больше, чем &amp;lt;math&amp;gt;(2t+1)&amp;lt;/math&amp;gt;. Если кодовое расстояние больше или равно, чем &amp;lt;math&amp;gt;(t+d+1)&amp;lt;/math&amp;gt;, то любая комбинация из &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; ошибок может быть исправлена и до &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;ошибок могут быть обнаружены. &lt;br /&gt;
Для множества из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; модулей в соответствующей системе могут быть представлены числа &amp;lt;math&amp;gt;(0, ..., M-1)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;M = lcm(m_1, ..., m_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Циклическим числом''' &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt; для каждого модуля &amp;lt;math&amp;gt;m_i&amp;lt;/math&amp;gt; назовём &amp;lt;math&amp;gt;c_i = M/m_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
=== Модули с попарно взаимно простыми циклическими числами ===&lt;br /&gt;
Построим теперь систему модулей с попарно взаимно простыми циклическими числами, которая поможет получит эффективный алгоритм обнаружения и коррекции ошибок. &lt;br /&gt;
&lt;br /&gt;
'''Построение 1'''. &lt;br /&gt;
#Выберем &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; попарно взаимно простых циклических чисел, не равных единице &amp;lt;math&amp;gt;(c_1, ..., c_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
#Получим систему модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt; следующим образом:&lt;br /&gt;
:&amp;lt;math&amp;gt;m_i = \frac{1}{c_i}\prod^n_{k=1}{c_k}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полученные модули обладают двумя свойствами:&lt;br /&gt;
#Наименьшие общие кратны всевозможных пар модулей равны между собой.&lt;br /&gt;
#Наибольшие общие делители всевозможных пар модулей различны.&lt;br /&gt;
&lt;br /&gt;
'''Теорема 1'''. Для построенной системы модулей кодовое расстояние равно &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество модулей.&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обнаружения ошибки ====&lt;br /&gt;
#Если &amp;lt;math&amp;gt;r_i \geqslant m_i&amp;lt;/math&amp;gt;, то произошла ошибка в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-том разряде.&lt;br /&gt;
#Если не выполняется хотя бы одно из следующей системы равенств:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_i|_{k_{ij}}=|r_j|_{k_{ij}}, k_{ij} = gcd(m_i, m_j)&amp;lt;/math&amp;gt;,&lt;br /&gt;
то произошла ошибка.&lt;br /&gt;
&lt;br /&gt;
'''Теорема 2'''. Для системы из четырёх модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4)&amp;lt;/math&amp;gt; ошибка в одном разряде влечёт за собой невыполнением как минимум двух, а как максимум трёх равенств из системы выше. Причём, если ошибка в &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;, то равенства, которые не выполняются, содержат &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм локализации ошибки ====&lt;br /&gt;
Теорема 2 даёт алгоритм локализации ошибки. Ошибочным является разряд, который содержится во всех равенствах, которые не выполняются.&lt;br /&gt;
==== Алгоритм коррекции ошибки ====&lt;br /&gt;
Предложим, что ошибка в &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\bar{r_i}&amp;lt;/math&amp;gt; - правильное значение. Тогда &amp;lt;math&amp;gt;\bar{r_i}&amp;lt;/math&amp;gt; можно найти, решая следующую систему уравнений:&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_i}|_{k_a} = |r_j|_{k_a}, k_a = gcd(m_i, m_j)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_i}|_{k_b} = |r_k|_{k_b}, k_b = gcd(m_i, m_k)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Решение заключается в составлении множеств &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \left \{ f = |r_j|_{k_a}  + k_a k_x : f &amp;lt; m_i, k_x \geq 0 \right \}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \left \{ g = |r_k|_{k_b}  + k_b k_y : g &amp;lt; m_i, k_y \geq 0 \right \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
и поиске пересечения &amp;lt;math&amp;gt;A \cap B&amp;lt;/math&amp;gt;. Можно доказать, что такое пересечение всегда непусто и состоит ровно из одного элемента.&lt;br /&gt;
&lt;br /&gt;
==== Примеры ====&lt;br /&gt;
'''Пример обнаружения одной ошибки.'''&lt;br /&gt;
Воспользуемся Построением 1 для получения системы модулей. Используя попарно взаимно простые циклические числа &amp;lt;math&amp;gt;(c_1, c_2, c_3, c_4)=(2, 3, 5, 7)&amp;lt;/math&amp;gt;, получим систему модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4)=(105, 70, 42, 30)&amp;lt;/math&amp;gt;. Пусть теперь в остаточном представлении &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4)=(30, 60, 30, 0)&amp;lt;/math&amp;gt; содержится одна ошибка. Проверяя совместность представления, найдём, что следующие равенства не выполняются:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{35} = |r_2|_{35}, 35 = gcd(105, 70)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{14} = |r_3k|_{14}, 14 = gcd(70, 42)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;r_2&amp;lt;/math&amp;gt; является общим в этих равенствах, ошибочным является остаток &amp;lt;math&amp;gt;60&amp;lt;/math&amp;gt;. Для того чтобы получить правильное значение, составим множества &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; как было описано выше:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \left \{ f = |r_1|_{35}  + 35 k_x : f &amp;lt; 70, k_x \geq 0 \right \}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \left \{ g = |r_3|_{14}  + 14 k_y : g &amp;lt; 70, k_y \geq 0 \right \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получим:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \left \{ 30, 65 \right \}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \left \{ 2,16,30,44,58\right \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом скорректированное значение &amp;lt;math&amp;gt;\{ \bar {r_2} \}= A \cap B = \{ 30 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необязательно вычислять множество &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; полностью. Так как &amp;lt;math&amp;gt;|r_1|_{35} &amp;gt; 14&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;k_y \geq 2&amp;lt;/math&amp;gt;. Вычисления элементов множеств следует прекратить, как только их пересечение больше не пусто.&lt;br /&gt;
'''Пример обнаружения двух и коррекции одной ошибки.'''&lt;br /&gt;
Для обнаружения двух и коррекции одной ошибки требуется по крайней мере 5 модулей и кодовое расстояние равное 4. Если мы выберем циклические числа &amp;lt;math&amp;gt;(2, 3, 5, 7, 11)&amp;lt;/math&amp;gt; мы получим набор модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4, m_5) = (1155, 770, 462, 330, 210)&amp;lt;/math&amp;gt;. Чтобы проверить, есть ли ошибки в остаточном представлении &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4, r_5)&amp;lt;/math&amp;gt;, нужно выяснить, какие из следующих равенств не выполняются:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{385} = |r_2|_{385}, 385 = gcd(1155, 770)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{231} = |r_3|_{231}, 231 = gcd(1155, 462)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{105} = |r_5|_{105}, 105 = gcd(1155, 210)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{154} = |r_3|_{154}, 154 = gcd(462, 770)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{110} = |r_4|_{110}, 110 = gcd(330, 770)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{70} = |r_5|_{70}, 70 = gcd(210, 770)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_3|_{66} = |r_4|_{66}, 66 = gcd(462, 330)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_3|_{42} = |r_5|_{42}, 42 = gcd(462, 210)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_4|_{30} = |r_5|_{30}, 30 = gcd(330, 210)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Следует отметить, что если три или четыре из равенств выше не выполняются, то обнаружена одна ошибка. Если их пять и больше, то ошибок две. Аналогично предыдущему примеру, можно построить три множества &amp;lt;math&amp;gt;A, B, C&amp;lt;/math&amp;gt;. Исправленное значение ошибочного разряда получим, найдя пересечение этих множеств:&lt;br /&gt;
&amp;lt;math&amp;gt;\{ \bar {r_i} \}= A \cap B \cap C&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Модули с произвольными циклическими числами ===&lt;br /&gt;
Если мы уберём ограничение на взаимную простоту циклических числе, то обнаружение и коррекция ошибки может быть всё ещё осуществлена сокращением динамического диапазона. Следующие теорема и следствие связывают кодовое расстояние и динамический диапазон.&lt;br /&gt;
&lt;br /&gt;
'''Теорема 3'''. Пусть есть множество модулей &amp;lt;math&amp;gt;(m_1, m_2, ..., m_n)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(l_1, l_2, ..., l_a)&amp;lt;/math&amp;gt; - множество наименьших общих кратных всевозможных различных пар модулей, где &amp;lt;math&amp;gt;a = C^2_n&amp;lt;/math&amp;gt;. Тогда, если &amp;lt;math&amp;gt;l = \min{(l_1, l_2, ..., l_a)}&amp;lt;/math&amp;gt;, то кодовое расстояние множества всех представлений чисел &amp;lt;math&amp;gt;\{0, ..., l-1\}&amp;lt;/math&amp;gt; в системе остаточных классов равно &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Следствие'''. Пусть есть множество модулей &amp;lt;math&amp;gt;(m_1, m_2, ..., m_n)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(l_1, l_2, ..., l_a)&amp;lt;/math&amp;gt; - множество наименьших общих кратных всевозможных кортежей из &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; различных модулей, где &amp;lt;math&amp;gt;a = C^i_n&amp;lt;/math&amp;gt;. Тогда, если &amp;lt;math&amp;gt;l = \min{(l_1, l_2, ..., l_a)}&amp;lt;/math&amp;gt;, то кодовое расстояние множества всех представлений чисел &amp;lt;math&amp;gt;\{0, ..., l-1\}&amp;lt;/math&amp;gt; в системе остаточных классов равно &amp;lt;math&amp;gt;n - 1 + i&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Далее будем предполагать, что ошибочный разряд только один. Из теоремы 3 следует, что для коррекции одной ошибки требуется множество из 4 модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4)&amp;lt;/math&amp;gt;. Пусть &amp;lt;math&amp;gt;l_1, l_2, l_3&amp;lt;/math&amp;gt; - соответственно наименьшее из НОК всех пар, наименьшее из НОК всех троек и НОК всех модулей. Из теоремы 3 и следствия из неё следует, что для множества чисел &amp;lt;math&amp;gt;\{0, ..., l_1-1\}&amp;lt;/math&amp;gt; кодовое расстояние соответствующего множества кодовых слов равно &amp;lt;math&amp;gt;3&amp;lt;/math&amp;gt;, а для множеств &amp;lt;math&amp;gt;\{0, ..., l_2-1\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{0, ..., l_3-1\}&amp;lt;/math&amp;gt; - не меньше &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; и не меньше &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; соответственно. Разделим множество всех кодовых слов на три подмножества:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \{x : 0 \leq x \leq l_1-1\}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \{x : l_1 \leq x \leq l_2-1\}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;C = \{x : l_2 \leq x \leq l_3-1\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для коррекции одной ошибки необходимо кодовое расстояние, равное трём, то есть все слова из &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; выходят за границы динамического диапазона. Пусть необходимо обнаружить/исправить одну ошибку в остаточном представлении.&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обнаружения ошибки ====&lt;br /&gt;
#Если &amp;lt;math&amp;gt;r_i \geqslant m_i&amp;lt;/math&amp;gt;, то произошла ошибка в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-том разряде.&lt;br /&gt;
#Если остаточное представление не является совместным и слово не лежит в динамическом диапазоне, то произошла ошибка. Для проверки нужно воспользоваться КТО для перевода числа из остаточного представления и проверить, выполняется ли &amp;lt;math&amp;gt;x \leq l_1-1&amp;lt;/math&amp;gt;.&lt;br /&gt;
#Если остаточное представление не является совместным, то произошла ошибка.&lt;br /&gt;
#Если остаточное представление является совместным и лежит в динамическом диапазоне, то ошибок нет.&lt;br /&gt;
==== Алгоритм коррекции ошибки ====&lt;br /&gt;
Начнём описание алгоритма со следующей леммы.&lt;br /&gt;
&lt;br /&gt;
'''Лемма 1'''. Существует и единственно кодовое слово в множестве &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt;&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%BA%D0%BE%D1%80%D1%80%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D0%BA_Rajendra_S._Katti</id>
		<title>Схема коррекции ошибок Rajendra S. Katti</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%BA%D0%BE%D1%80%D1%80%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D0%BA_Rajendra_S._Katti"/>
				<updated>2013-07-22T13:12:04Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Введение ==&lt;br /&gt;
Метод, описанный автором, основан на использовании избыточной системы остаточных классов. Недостатки представления чисел в такой системе с целью коррекции ошибок при вычислениях покажем на примере.&lt;br /&gt;
&lt;br /&gt;
Пусть избыточная СОК определяется следующими модулями &amp;lt;math&amp;gt; m_1 = 3, m_2 = 4, m_3 = 5, m_4 = 7&amp;lt;/math&amp;gt;, а динамический диапазон определяется &amp;lt;math&amp;gt;m_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;m_2&amp;lt;/math&amp;gt; и соответственно равен &amp;lt;math&amp;gt;\{0,...,11\}&amp;lt;/math&amp;gt;, а модули &amp;lt;math&amp;gt;m_3, m_4&amp;lt;/math&amp;gt; являются дополнительными и необходимы для проверки на ошибки.&lt;br /&gt;
&lt;br /&gt;
Натуральное число из динамического диапазона может быть восстановлено по любым трём из четырёх остатков по представленным модулям. Например, число &amp;lt;math&amp;gt;x=5=(2,1,0,2)&amp;lt;/math&amp;gt; может быть представлено как &amp;lt;math&amp;gt;(2,1,0)&amp;lt;/math&amp;gt; в системе модулей &amp;lt;math&amp;gt;\{m_1, m_2, m_3\}&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;(2,0,2), (1,0,2)&amp;lt;/math&amp;gt; в системах &amp;lt;math&amp;gt;\{m_1, m_3, m_4\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{m_2, m_3, m_4\}&amp;lt;/math&amp;gt; соответственно. Поэтому, если одна цифра отбрасывается в представлении &amp;lt;math&amp;gt;(2,1,0,2)&amp;lt;/math&amp;gt;, правильный результат восстановления будет получен тогда и только тогда, когда отбрасываемая цифра ошибочна. Итак, обнаружение ошибок и коррекция выполняется следующим образом:&lt;br /&gt;
# Если число лежит вне динамического диапазона - произошла ошибка.&lt;br /&gt;
# Остатки отбрасываются по одному и если в результате одного из отбрасываний полученное число лежит в динамическом диапазоне, то отброшенный остаток является ошибочным.&lt;br /&gt;
# Корректное значение остатка получается расширением полученного на шаге 2 множества модулей, остатки по которым не содержат ошибок.&lt;br /&gt;
&lt;br /&gt;
Такой подход требует много времени и вычислительных ресурсов. Ниже будет предложена новая схема обнаружения и коррекции ошибок на основе СОК.&lt;br /&gt;
&lt;br /&gt;
== Модули, имеющие общие делители ==&lt;br /&gt;
Каждый набор остатков необязательно соответствует числу из динамического диапазона, если модули не являются попарно взаимно простыми. Легко показать, что такое соответствие есть тогда и только тогда, когда&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_i|_k = |r_j|_k&amp;lt;/math&amp;gt;,&lt;br /&gt;
выполняется для любых &amp;lt;math&amp;gt;i, j&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;k = gcd(r_i, r_j)&amp;lt;/math&amp;gt;. Таким образом, ошибочный разряд может быть найден выполнением только простой операции вычисления остатка.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, демонстрирующий, как можно проверить набор остатков на наличие ошибок. Проверим набор &amp;lt;math&amp;gt;(2, 6, 30, 42)&amp;lt;/math&amp;gt; в системе модулей &amp;lt;math&amp;gt;\{4, 15, 36, 48\}&amp;lt;/math&amp;gt;. Наибольшие общие делители всевозможных пар модулей соответственно равны: &amp;lt;math&amp;gt;gcd(4, 15) = 1, gcd(4, 36) = 4, gcd(4, 48) = 4, gcd(15, 36) = 3, gcd(15, 48) = 3, gcd(36, 48) = 12&amp;lt;/math&amp;gt;.&lt;br /&gt;
Используя описанное выше соотношение для проверки, получаем: &amp;lt;math&amp;gt;|2|_4=|30|_4, |2|_4=|42|_4, |6|_3 = |30|_3, |6|_3=|42|_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; |30|_{12}=|42|_{12}&amp;lt;/math&amp;gt;. То есть ошибок нет и число может быть восстановлено с использованием китайской теоремы об остатках (КТО) для модулей, имеющих нетривиальные общие делители.&lt;br /&gt;
&lt;br /&gt;
'''КТО для системы модулей, попарно не взаимно простых'''. Пусть есть представление &amp;lt;math&amp;gt;(r_1, ..., r_n)&amp;lt;/math&amp;gt; натурального числа &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, определяемое системой модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt;. Тогда&lt;br /&gt;
:&amp;lt;math&amp;gt;|x|_M = \left | \sum^{n}_{i=1} {{{\alpha}_i}r_i} \right |&amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt; {\alpha}_i &amp;lt;/math&amp;gt;- число, такое что &amp;lt;math&amp;gt;|{\alpha}_i|_M = 0, |{\alpha}_i|_{\frac{M}{{\mu}_i}} = 1 &amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt; {\mu}_i &amp;lt;/math&amp;gt; - числа, такие что &amp;lt;math&amp;gt; M = \prod^n_{i=1}{{\mu}_i} &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; {\mu}_i &amp;lt;/math&amp;gt; делит &amp;lt;math&amp;gt; m_i &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; M = lcm(m_1, ..., m_n) &amp;lt;/math&amp;gt;. Если для некоторого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; такое &amp;lt;math&amp;gt;{\alpha}_i&amp;lt;/math&amp;gt; не существует, то соответствующее слагаемое в сумме опускается. &lt;br /&gt;
&lt;br /&gt;
Операции над числами остаются корректными и в системе не взаимно простых попарно модулей.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Если в множестве модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt; есть имеющие нетривиальный общий делитель, то каждый набор остатков &amp;lt;math&amp;gt;(r_1, ..., r_n)&amp;lt;/math&amp;gt; необязательно соответствует некоторому числу. Каждый набор, для которого такое соответствие имеет место, будем называть '''кодовым словом'''.&lt;br /&gt;
&lt;br /&gt;
'''Расстоянием''' между двумя представлениями чисел в СОК(кодовыми словами) будем считать количество разрядов, в которых кодовые слова различаются между собой. &lt;br /&gt;
&lt;br /&gt;
'''Кодовым расстоянием''' назовём минимальное расстояние среди всех пар кодовых слов.&lt;br /&gt;
&lt;br /&gt;
Чтобы обнаружить и исправить &amp;lt;math&amp;gt;d-1&amp;lt;/math&amp;gt; или меньше ошибок, необходимо и достаточно, чтобы кодовое расстояние было не меньше &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;. Не более &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; ошибок может быть обнаружено и исправлено тогда и только тогда, когда кодовое расстояние больше, чем &amp;lt;math&amp;gt;(2t+1)&amp;lt;/math&amp;gt;. Если кодовое расстояние больше или равно, чем &amp;lt;math&amp;gt;(t+d+1)&amp;lt;/math&amp;gt;, то любая комбинация из &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; ошибок может быть исправлена и до &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;ошибок могут быть обнаружены. &lt;br /&gt;
Для множества из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; модулей в соответствующей системе могут быть представлены числа &amp;lt;math&amp;gt;(0, ..., M-1)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;M = lcm(m_1, ..., m_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Циклическим числом''' &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt; для каждого модуля &amp;lt;math&amp;gt;m_i&amp;lt;/math&amp;gt; назовём &amp;lt;math&amp;gt;c_i = M/m_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
=== Модули с попарно взаимно простыми циклическими числами ===&lt;br /&gt;
Построим теперь систему модулей с попарно взаимно простыми циклическими числами, которая поможет получит эффективный алгоритм обнаружения и коррекции ошибок. &lt;br /&gt;
&lt;br /&gt;
'''Построение 1'''. &lt;br /&gt;
#Выберем &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; попарно взаимно простых циклических чисел, не равных единице &amp;lt;math&amp;gt;(c_1, ..., c_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
#Получим систему модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt; следующим образом:&lt;br /&gt;
:&amp;lt;math&amp;gt;m_i = \frac{1}{c_i}\prod^n_{k=1}{c_k}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полученные модули обладают двумя свойствами:&lt;br /&gt;
#Наименьшие общие кратны всевозможных пар модулей равны между собой.&lt;br /&gt;
#Наибольшие общие делители всевозможных пар модулей различны.&lt;br /&gt;
&lt;br /&gt;
'''Теорема 1'''. Для построенной системы модулей кодовое расстояние равно &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество модулей.&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обнаружения ошибки ====&lt;br /&gt;
#Если &amp;lt;math&amp;gt;r_i \geqslant m_i&amp;lt;/math&amp;gt;, то произошла ошибка в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-том разряде.&lt;br /&gt;
#Если не выполняется хотя бы одно из следующей системы равенств:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_i|_{k_{ij}}=|r_j|_{k_{ij}}, k_{ij} = gcd(m_i, m_j)&amp;lt;/math&amp;gt;,&lt;br /&gt;
то произошла ошибка.&lt;br /&gt;
&lt;br /&gt;
'''Теорема 2'''. Для системы из четырёх модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4)&amp;lt;/math&amp;gt; ошибка в одном разряде влечёт за собой невыполнением как минимум двух, а как максимум трёх равенств из системы выше. Причём, если ошибка в &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;, то равенства, которые не выполняются, содержат &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм локализации ошибки ====&lt;br /&gt;
Теорема 2 даёт алгоритм локализации ошибки. Ошибочным является разряд, который содержится во всех равенствах, которые не выполняются.&lt;br /&gt;
==== Алгоритм коррекции ошибки ====&lt;br /&gt;
Предложим, что ошибка в &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\bar{r_i}&amp;lt;/math&amp;gt; - правильное значение. Тогда &amp;lt;math&amp;gt;\bar{r_i}&amp;lt;/math&amp;gt; можно найти, решая следующую систему уравнений:&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_i}|_{k_a} = |r_j|_{k_a}, k_a = gcd(m_i, m_j)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_i}|_{k_b} = |r_k|_{k_b}, k_b = gcd(m_i, m_k)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Решение заключается в составлении множеств &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \left \{ f = |r_j|_{k_a}  + k_a k_x : f &amp;lt; m_i, k_x \geq 0 \right \}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \left \{ g = |r_k|_{k_b}  + k_b k_y : g &amp;lt; m_i, k_y \geq 0 \right \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
и поиске пересечения &amp;lt;math&amp;gt;A \cap B&amp;lt;/math&amp;gt;. Можно доказать, что такое пересечение всегда непусто и состоит ровно из одного элемента.&lt;br /&gt;
&lt;br /&gt;
==== Примеры ====&lt;br /&gt;
'''Пример обнаружения одной ошибки.'''&lt;br /&gt;
Воспользуемся Построением 1 для получения системы модулей. Используя попарно взаимно простые циклические числа &amp;lt;math&amp;gt;(c_1, c_2, c_3, c_4)=(2, 3, 5, 7)&amp;lt;/math&amp;gt;, получим систему модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4)=(105, 70, 42, 30)&amp;lt;/math&amp;gt;. Пусть теперь в остаточном представлении &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4)=(30, 60, 30, 0)&amp;lt;/math&amp;gt; содержится одна ошибка. Проверяя совместность представления, найдём, что следующие равенства не выполняются:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{35} = |r_2|_{35}, 35 = gcd(105, 70)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{14} = |r_3k|_{14}, 14 = gcd(70, 42)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;math&amp;gt;r_2&amp;lt;/math&amp;gt; является общим в этих равенствах, ошибочным является остаток &amp;lt;math&amp;gt;60&amp;lt;/math&amp;gt;. Для того чтобы получить правильное значение, составим множества &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; как было описано выше:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \left \{ f = |r_1|_{35}  + 35 k_x : f &amp;lt; 70, k_x \geq 0 \right \}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \left \{ g = |r_3|_{14}  + 14 k_y : g &amp;lt; 70, k_y \geq 0 \right \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получим:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \left \{ 30, 65 \right \}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \left \{ 2,16,30,44,58\right \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом скорректированное значение &amp;lt;math&amp;gt;\{ \bar {r_2} \}= A \cap B = \{ 30 \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необязательно вычислять множество &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; полностью. Так как &amp;lt;math&amp;gt;|r_1|_{35} &amp;gt; 14&amp;lt;/math&amp;gt;, то &amp;lt;math&amp;gt;k_y \geq 2&amp;lt;/math&amp;gt;. Вычисления элементов множеств следует прекратить, как только их пересечение больше не пусто.&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%BA%D0%BE%D1%80%D1%80%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D0%BA_Rajendra_S._Katti</id>
		<title>Схема коррекции ошибок Rajendra S. Katti</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%BA%D0%BE%D1%80%D1%80%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D0%BA_Rajendra_S._Katti"/>
				<updated>2013-07-22T12:55:22Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Введение ==&lt;br /&gt;
Метод, описанный автором, основан на использовании избыточной системы остаточных классов. Недостатки представления чисел в такой системе с целью коррекции ошибок при вычислениях покажем на примере.&lt;br /&gt;
&lt;br /&gt;
Пусть избыточная СОК определяется следующими модулями &amp;lt;math&amp;gt; m_1 = 3, m_2 = 4, m_3 = 5, m_4 = 7&amp;lt;/math&amp;gt;, а динамический диапазон определяется &amp;lt;math&amp;gt;m_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;m_2&amp;lt;/math&amp;gt; и соответственно равен &amp;lt;math&amp;gt;\{0,...,11\}&amp;lt;/math&amp;gt;, а модули &amp;lt;math&amp;gt;m_3, m_4&amp;lt;/math&amp;gt; являются дополнительными и необходимы для проверки на ошибки.&lt;br /&gt;
&lt;br /&gt;
Натуральное число из динамического диапазона может быть восстановлено по любым трём из четырёх остатков по представленным модулям. Например, число &amp;lt;math&amp;gt;x=5=(2,1,0,2)&amp;lt;/math&amp;gt; может быть представлено как &amp;lt;math&amp;gt;(2,1,0)&amp;lt;/math&amp;gt; в системе модулей &amp;lt;math&amp;gt;\{m_1, m_2, m_3\}&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;(2,0,2), (1,0,2)&amp;lt;/math&amp;gt; в системах &amp;lt;math&amp;gt;\{m_1, m_3, m_4\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{m_2, m_3, m_4\}&amp;lt;/math&amp;gt; соответственно. Поэтому, если одна цифра отбрасывается в представлении &amp;lt;math&amp;gt;(2,1,0,2)&amp;lt;/math&amp;gt;, правильный результат восстановления будет получен тогда и только тогда, когда отбрасываемая цифра ошибочна. Итак, обнаружение ошибок и коррекция выполняется следующим образом:&lt;br /&gt;
# Если число лежит вне динамического диапазона - произошла ошибка.&lt;br /&gt;
# Остатки отбрасываются по одному и если в результате одного из отбрасываний полученное число лежит в динамическом диапазоне, то отброшенный остаток является ошибочным.&lt;br /&gt;
# Корректное значение остатка получается расширением полученного на шаге 2 множества модулей, остатки по которым не содержат ошибок.&lt;br /&gt;
&lt;br /&gt;
Такой подход требует много времени и вычислительных ресурсов. Ниже будет предложена новая схема обнаружения и коррекции ошибок на основе СОК.&lt;br /&gt;
&lt;br /&gt;
== Модули, имеющие общие делители ==&lt;br /&gt;
Каждый набор остатков необязательно соответствует числу из динамического диапазона, если модули не являются попарно взаимно простыми. Легко показать, что такое соответствие есть тогда и только тогда, когда&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_i|_k = |r_j|_k&amp;lt;/math&amp;gt;,&lt;br /&gt;
выполняется для любых &amp;lt;math&amp;gt;i, j&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;k = gcd(r_i, r_j)&amp;lt;/math&amp;gt;. Таким образом, ошибочный разряд может быть найден выполнением только простой операции вычисления остатка.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, демонстрирующий, как можно проверить набор остатков на наличие ошибок. Проверим набор &amp;lt;math&amp;gt;(2, 6, 30, 42)&amp;lt;/math&amp;gt; в системе модулей &amp;lt;math&amp;gt;\{4, 15, 36, 48\}&amp;lt;/math&amp;gt;. Наибольшие общие делители всевозможных пар модулей соответственно равны: &amp;lt;math&amp;gt;gcd(4, 15) = 1, gcd(4, 36) = 4, gcd(4, 48) = 4, gcd(15, 36) = 3, gcd(15, 48) = 3, gcd(36, 48) = 12&amp;lt;/math&amp;gt;.&lt;br /&gt;
Используя описанное выше соотношение для проверки, получаем: &amp;lt;math&amp;gt;|2|_4=|30|_4, |2|_4=|42|_4, |6|_3 = |30|_3, |6|_3=|42|_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; |30|_{12}=|42|_{12}&amp;lt;/math&amp;gt;. То есть ошибок нет и число может быть восстановлено с использованием китайской теоремы об остатках (КТО) для модулей, имеющих нетривиальные общие делители.&lt;br /&gt;
&lt;br /&gt;
'''КТО для системы модулей, попарно не взаимно простых'''. Пусть есть представление &amp;lt;math&amp;gt;(r_1, ..., r_n)&amp;lt;/math&amp;gt; натурального числа &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, определяемое системой модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt;. Тогда&lt;br /&gt;
:&amp;lt;math&amp;gt;|x|_M = \left | \sum^{n}_{i=1} {{{\alpha}_i}r_i} \right |&amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt; {\alpha}_i &amp;lt;/math&amp;gt;- число, такое что &amp;lt;math&amp;gt;|{\alpha}_i|_M = 0, |{\alpha}_i|_{\frac{M}{{\mu}_i}} = 1 &amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt; {\mu}_i &amp;lt;/math&amp;gt; - числа, такие что &amp;lt;math&amp;gt; M = \prod^n_{i=1}{{\mu}_i} &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; {\mu}_i &amp;lt;/math&amp;gt; делит &amp;lt;math&amp;gt; m_i &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; M = lcm(m_1, ..., m_n) &amp;lt;/math&amp;gt;. Если для некоторого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; такое &amp;lt;math&amp;gt;{\alpha}_i&amp;lt;/math&amp;gt; не существует, то соответствующее слагаемое в сумме опускается. &lt;br /&gt;
&lt;br /&gt;
Операции над числами остаются корректными и в системе не взаимно простых попарно модулей.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
Если в множестве модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt; есть имеющие нетривиальный общий делитель, то каждый набор остатков &amp;lt;math&amp;gt;(r_1, ..., r_n)&amp;lt;/math&amp;gt; необязательно соответствует некоторому числу. Каждый набор, для которого такое соответствие имеет место, будем называть '''кодовым словом'''.&lt;br /&gt;
&lt;br /&gt;
'''Расстоянием''' между двумя представлениями чисел в СОК(кодовыми словами) будем считать количество разрядов, в которых кодовые слова различаются между собой. &lt;br /&gt;
&lt;br /&gt;
'''Кодовым расстоянием''' назовём минимальное расстояние среди всех пар кодовых слов.&lt;br /&gt;
&lt;br /&gt;
Чтобы обнаружить и исправить &amp;lt;math&amp;gt;d-1&amp;lt;/math&amp;gt; или меньше ошибок, необходимо и достаточно, чтобы кодовое расстояние было не меньше &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;. Не более &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; ошибок может быть обнаружено и исправлено тогда и только тогда, когда кодовое расстояние больше, чем &amp;lt;math&amp;gt;(2t+1)&amp;lt;/math&amp;gt;. Если кодовое расстояние больше или равно, чем &amp;lt;math&amp;gt;(t+d+1)&amp;lt;/math&amp;gt;, то любая комбинация из &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; ошибок может быть исправлена и до &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;ошибок могут быть обнаружены. &lt;br /&gt;
Для множества из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; модулей в соответствующей системе могут быть представлены числа &amp;lt;math&amp;gt;(0, ..., M-1)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;M = lcm(m_1, ..., m_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Циклическим числом''' &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt; для каждого модуля &amp;lt;math&amp;gt;m_i&amp;lt;/math&amp;gt; назовём &amp;lt;math&amp;gt;c_i = M/m_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
=== Модули с попарно взаимно простыми циклическими числами ===&lt;br /&gt;
Построим теперь систему модулей с попарно взаимно простыми циклическими числами, которая поможет получит эффективный алгоритм обнаружения и коррекции ошибок. &lt;br /&gt;
&lt;br /&gt;
'''Построение 1'''. &lt;br /&gt;
#Выберем &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; попарно взаимно простых циклических чисел, не равных единице &amp;lt;math&amp;gt;(c_1, ..., c_n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
#Получим систему модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt; следующим образом:&lt;br /&gt;
:&amp;lt;math&amp;gt;m_i = \frac{1}{c_i}\prod^n_{k=1}{c_k}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Полученные модули обладают двумя свойствами:&lt;br /&gt;
#Наименьшие общие кратны всевозможных пар модулей равны между собой.&lt;br /&gt;
#Наибольшие общие делители всевозможных пар модулей различны.&lt;br /&gt;
&lt;br /&gt;
'''Теорема 1'''. Для построенной системы модулей кодовое расстояние равно &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество модулей.&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм обнаружения ошибки ====&lt;br /&gt;
#Если &amp;lt;math&amp;gt;r_i \geqslant m_i&amp;lt;/math&amp;gt;, то произошла ошибка в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-том разряде.&lt;br /&gt;
#Если не выполняется хотя бы одно из следующей системы равенств:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_i|_{k_{ij}}=|r_j|_{k_{ij}}, k_{ij} = gcd(m_i, m_j)&amp;lt;/math&amp;gt;,&lt;br /&gt;
то произошла ошибка.&lt;br /&gt;
&lt;br /&gt;
'''Теорема 2'''. Для системы из четырёх модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4)&amp;lt;/math&amp;gt; ошибка в одном разряде влечёт за собой невыполнением как минимум двух, а как максимум трёх равенств из системы выше. Причём, если ошибка в &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;, то равенства, которые не выполняются, содержат &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Алгоритм локализации ошибки ====&lt;br /&gt;
Теорема 2 даёт алгоритм локализации ошибки. Ошибочным является разряд, который содержится во всех равенствах, которые не выполняются.&lt;br /&gt;
==== Алгоритм коррекции ошибки ====&lt;br /&gt;
Предложим, что ошибка в &amp;lt;math&amp;gt;r_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\bar{r_i}&amp;lt;/math&amp;gt; - правильное значение. Тогда &amp;lt;math&amp;gt;\bar{r_i}&amp;lt;/math&amp;gt; можно найти, решая следующую систему уравнений:&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_i}|_{k_a} = |r_j|_{k_a}, k_a = gcd(m_i, m_j)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|\bar{r_i}|_{k_b} = |r_k|_{k_b}, k_b = gcd(m_i, m_k)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Решение заключается в составлении множеств &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt;A = \left \{ f = |r_j|_{k_a}  + k_a k_x : f &amp;lt; m_i, k_x \geq 0 \right \}&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;B = \left \{ g = |r_k|_{k_b}  + k_b k_y : g &amp;lt; m_i, k_y \geq 0 \right \}&amp;lt;/math&amp;gt;.&lt;br /&gt;
и поиске пересечения &amp;lt;math&amp;gt;A \cap B&amp;lt;/math&amp;gt;. Можно доказать, что такое пересечение всегда непусто и состоит ровно из одного элемента.&lt;br /&gt;
&lt;br /&gt;
==== Примеры ====&lt;br /&gt;
'''Пример обнаружения одной ошибки.'''&lt;br /&gt;
Воспользуемся Построением 1 для получения системы модулей. Используя попарно взаимно простые циклические числа &amp;lt;math&amp;gt;(c_1, c_2, c_3, c_4)=(2, 3, 5, 7)&amp;lt;/math&amp;gt;, получим систему модулей &amp;lt;math&amp;gt;(m_1, m_2, m_3, m_4)=(105, 70, 42, 30)&amp;lt;/math&amp;gt;. Пусть теперь в остаточном представлении &amp;lt;math&amp;gt;(r_1, r_2, r_3, r_4)=(30, 60, 30, 0)&amp;lt;/math&amp;gt; содержится одна ошибка. Проверяя совместность представления, найдём, что следующие равенства не выполняются:&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_1|_{35} = |r_2|_{35}, 35 = gcd(105, 70)&amp;lt;/math&amp;gt;,&lt;br /&gt;
:&amp;lt;math&amp;gt;|r_2|_{14} = |r_3k|_{14}, 14 = gcd(70, 42)&amp;lt;/math&amp;gt;.&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%BA%D0%BE%D1%80%D1%80%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D0%BA_Rajendra_S._Katti</id>
		<title>Схема коррекции ошибок Rajendra S. Katti</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A1%D1%85%D0%B5%D0%BC%D0%B0_%D0%BA%D0%BE%D1%80%D1%80%D0%B5%D0%BA%D1%86%D0%B8%D0%B8_%D0%BE%D1%88%D0%B8%D0%B1%D0%BE%D0%BA_Rajendra_S._Katti"/>
				<updated>2013-07-22T09:41:05Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: Новая страница: «== Введение == Метод, описанный автором, основан на использовании избыточной системы оста…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Введение ==&lt;br /&gt;
Метод, описанный автором, основан на использовании избыточной системы остаточных классов. Недостатки представления чисел в такой системе с целью коррекции ошибок при вычислениях покажем на примере.&lt;br /&gt;
&lt;br /&gt;
Пусть избыточная СОК определяется следующими модулями &amp;lt;math&amp;gt; m_1 = 3, m_2 = 4, m_3 = 5, m_4 = 7&amp;lt;/math&amp;gt;, а динамический диапазон определяется &amp;lt;math&amp;gt;m_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;m_2&amp;lt;/math&amp;gt; и соответственно равен &amp;lt;math&amp;gt;\{0,...,11\}&amp;lt;/math&amp;gt;, а модули &amp;lt;math&amp;gt;m_3, m_4&amp;lt;/math&amp;gt; являются дополнительными и необходимы для проверки на ошибки.&lt;br /&gt;
&lt;br /&gt;
Натуральное число из динамического диапазона может быть восстановлено по любым трём из четырёх остатков по представленным модулям. Например, число &amp;lt;math&amp;gt;x=5=(2,1,0,2)&amp;lt;/math&amp;gt; может быть представлено как &amp;lt;math&amp;gt;(2,1,0)&amp;lt;/math&amp;gt; в системе модулей &amp;lt;math&amp;gt;\{m_1, m_2, m_3\}&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;(2,0,2), (1,0,2)&amp;lt;/math&amp;gt; в системах &amp;lt;math&amp;gt;\{m_1, m_3, m_4\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{m_2, m_3, m_4\}&amp;lt;/math&amp;gt; соответственно. Поэтому, если одна цифра отбрасывается в представлении &amp;lt;math&amp;gt;(2,1,0,2)&amp;lt;/math&amp;gt;, правильный результат восстановления будет получен тогда и только тогда, когда отбрасываемая цифра ошибочна. Таким образом, обнаружение ошибок и коррекция выполняется следующим образом:&lt;br /&gt;
# Если число лежит вне динамического диапазона - произошла ошибка.&lt;br /&gt;
# Остатки отбрасываются по одному и если в результате одного из отбрасываний полученное число лежит в динамическом диапазоне, то отброшенный остаток является ошибочным.&lt;br /&gt;
# Корректное значение остатка получается расширением полученного на шаге 2 множества модулей, остатки по которым не содержат ошибок.&lt;br /&gt;
&lt;br /&gt;
Такой подход требует много времени и вычислительных ресурсов. Ниже будет предложена новая схема обнаружения и коррекции ошибок на основе СОК.&lt;br /&gt;
&lt;br /&gt;
== Модули, имеющие общие делители ==&lt;br /&gt;
Каждый набор остатков необязательно соответствует числу из динамического диапазона, если модули не являются попарно взаимно простыми. Легко показать, что такое соответствие есть тогда и только тогда, когда&lt;br /&gt;
: &amp;lt;math&amp;gt;|r_i|_k = |r_j|_k&amp;lt;/math&amp;gt;,&lt;br /&gt;
выполняется для любых &amp;lt;math&amp;gt;i, j&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;k = gcd(r_i, r_j)&amp;lt;/math&amp;gt;. Таким образом, ошибочный разряд может быть найден выполнением только простой операции вычисления остатка.&lt;br /&gt;
&lt;br /&gt;
Приведём пример, демонстрирующий, как можно проверить набор остатков на наличие ошибок. Проверим набор &amp;lt;math&amp;gt;(2, 6, 30, 42)&amp;lt;/math&amp;gt; в системе модулей &amp;lt;math&amp;gt;\{4, 15, 36, 48\}&amp;lt;/math&amp;gt;. Наибольшие общие делители всевозможных пар модулей соответственно равны: &amp;lt;math&amp;gt;gcd(4, 15) = 1, gcd(4, 36) = 4, gcd(4, 48) = 4, gcd(15, 36) = 3, gcd(15, 48) = 3, gcd(36, 48) = 12&amp;lt;/math&amp;gt;.&lt;br /&gt;
Используя описанное выше соотношение для проверки, получаем: &amp;lt;math&amp;gt;|2|_4=|30|_4, |2|_4=|42|_4, |6|_3 = |30|_3, |6|_3=|42|_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; |30|_{12}=|42|_{12}&amp;lt;/math&amp;gt;. То есть ошибок нет и число может быть восстановлено с использованием китайской теоремы об остатках (КТО) для модулей, имеющих нетривиальные общие делители.&lt;br /&gt;
&lt;br /&gt;
'''КТО для системы модулей, не взаимно простых попарно'''. Пусть есть представление &amp;lt;math&amp;gt;(r_1, ..., r_n)&amp;lt;/math&amp;gt; натурального числа &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, определяемое системой модулей &amp;lt;math&amp;gt;(m_1, ..., m_n)&amp;lt;/math&amp;gt;. Тогда&lt;br /&gt;
:&amp;lt;math&amp;gt;|x|_M = \left | \sum^{n}_{i=1} {{{\alpha}_i}r_i} \right |&amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt; {\alpha}_i &amp;lt;/math&amp;gt;- число, такое что &amp;lt;math&amp;gt;|{\alpha}_i|_M = 0, |{\alpha}_i|_{\frac{M}{{\mu}_i}} = 1 &amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt; {\mu}_i &amp;lt;/math&amp;gt; - числа, такие что &amp;lt;math&amp;gt; M = \prod^n_{i=1}{{\mu}_i} &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; {\mu}_i &amp;lt;/math&amp;gt; делит &amp;lt;math&amp;gt; m_i &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; M = lcm(m_1, ..., m_n) &amp;lt;/math&amp;gt;. Если для некоторого &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; такое &amp;lt;math&amp;gt;{\alpha}_i&amp;lt;/math&amp;gt; не существует, то соответствующее слагаемое в сумме опускается. &lt;br /&gt;
&lt;br /&gt;
Операции над числами остаются корректными и в системе не взаимно простых модулей.&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80_%D1%81_%D0%BA%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D0%BE%D0%B9_%D0%B8%D0%BC%D0%BF%D1%83%D0%BB%D1%8C%D1%81%D0%BD%D0%BE%D0%B9_%D1%85%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%BE%D0%B9</id>
		<title>Фильтр с конечной импульсной характеристикой</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80_%D1%81_%D0%BA%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D0%BE%D0%B9_%D0%B8%D0%BC%D0%BF%D1%83%D0%BB%D1%8C%D1%81%D0%BD%D0%BE%D0%B9_%D1%85%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%BE%D0%B9"/>
				<updated>2013-07-15T14:02:23Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Фильтр с конечной импульсной характеристикой''' ('''Нерекурсивный фильтр''', '''КИХ-фильтр''') или FIR-фильтр (FIR сокр. от finite impulse response — конечная импульсная характеристика) — один из видов линейных цифровых фильтров, характерной особенностью которого является ограниченность по времени его импульсной характеристики (с какого-то момента времени она становится точно равной нулю). Такой фильтр называют ещё нерекурсивным из-за отсутствия обратной связи. Знаменатель передаточной функции такого фильтра — некая константа.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики ==&lt;br /&gt;
Разностное уравнение, описывающее связь между входным и выходным сигналами фильтра:&lt;br /&gt;
&amp;lt;math&amp;gt;y\left (n\right)=b_0 x\left(n\right)+ b_1 x\left(n-1 \right)+...+b_P x\left(n-P \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; — порядок фильтра, &amp;lt;math&amp;gt;x(n)&amp;lt;/math&amp;gt; — входной сигнал, &amp;lt;math&amp;gt;y(n)&amp;lt;/math&amp;gt; — выходной сигнал, а &amp;lt;math&amp;gt;b_{i}&amp;lt;/math&amp;gt; — коэффициенты фильтра. Иными словами, значение любого отсчета выходного сигнала определяется суммой масштабированных значений &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; предыдущих отсчетов. Можно сказать иначе: значение выхода фильтра в любой момент времени есть значение отклика на мгновенное значение входа и сумма всех постепенно затухающих откликов &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; предыдущих отсчетов сигнала, которые всё ещё оказывают влияние на выход (после &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;-отсчетов импульсная переходная функция становится равной нулю, как уже было сказано, поэтому все члены после &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;-го тоже станут равными нулю). Запишем предыдущее уравнение в более ёмком виде:&lt;br /&gt;
: &amp;lt;math&amp;gt;y \left( n \right) = \sum_{i=0}^{P} b_i x \left( n-i \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
Для того, чтобы найти ядро фильтра положим&lt;br /&gt;
: &amp;lt;math&amp;gt;x(n) = \delta(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;\delta(n)&amp;lt;/math&amp;gt; — дельта-функция. Тогда импульсная характеристика КИХ-фильтра может быть записана как:&lt;br /&gt;
: &amp;lt;math&amp;gt;h\left (n\right)=\sum_{i=0}^{P}b_i \delta\left(n-i\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
Z-преобразование импульсной характеристики даёт нам передаточную функцию КИХ-фильтра:&lt;br /&gt;
: &amp;lt;math&amp;gt;H\left(z\right)=\sum_{i=0}^{P}b_i z^{-i}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства ==&lt;br /&gt;
КИХ-фильтр обладает рядом полезных свойств, из-за которых он иногда более предпочтителен в использовании, чем БИХ-фильтр. Вот некоторые из них:&lt;br /&gt;
* КИХ-фильтры устойчивы.&lt;br /&gt;
* КИХ-фильтры при реализации не требуют наличия обратной связи.&lt;br /&gt;
* Фаза КИХ-фильтров может быть сделана линейной&lt;br /&gt;
&lt;br /&gt;
== Прямая форма КИХ фильтра ==&lt;br /&gt;
КИХ фильтры могут быть реализованы с использованием трех элементов: умножитель, сумматор и блок задержки. Вариант, показанный на рисунке, есть прямая реализация КИХ-фильтров типа 1.&lt;br /&gt;
[[Файл:FIR Filter.png|center|300px|thumb|Реализация прямой формы КИХ фильтра]]&lt;br /&gt;
&lt;br /&gt;
== Пример программы ==&lt;br /&gt;
Ниже приведен пример программы КИХ-фильтра, написанный на C :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 100 // порядок фильтра&lt;br /&gt;
float h[N] = { #include “f1.h” }; //вставка файла с известными коэффициентами фильтра&lt;br /&gt;
float x[N];&lt;br /&gt;
float y[N];&lt;br /&gt;
&lt;br /&gt;
short my_FIR(short sample_data)&lt;br /&gt;
{&lt;br /&gt;
  float result = 0;&lt;br /&gt;
&lt;br /&gt;
  for ( int i = N - 2 ; i &amp;gt;= 0 ; i-- )&lt;br /&gt;
  {&lt;br /&gt;
    x[i + 1] = x[i];&lt;br /&gt;
    y[i + 1] = y[i];&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  x[0] = (float)sample_data;&lt;br /&gt;
  &lt;br /&gt;
  for (int k = 0; k &amp;lt; N; k++)&lt;br /&gt;
  {&lt;br /&gt;
    result = result + x[k]*h[k];&lt;br /&gt;
  }&lt;br /&gt;
  y[0] = result;&lt;br /&gt;
&lt;br /&gt;
  return ((short)result);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Построение КИХ-фильтров ==&lt;br /&gt;
Построение КИХ-фильтров заключается в выборе коэффициентов фильтра таким образом, чтобы полученная система имела требуемые характеристики. Чаще всего фильтр строят по заданной амплитудно-частотной характеристике. Существуют разные методы построения КИХ-фильтров:&lt;br /&gt;
# Построение методом окна&lt;br /&gt;
# Метод частотной выборки&lt;br /&gt;
# Метод наименьших квадратов&lt;br /&gt;
# Метод Паркса-Макклиллана (также известный как Equiripple, Optimal, или Minimax метод). Обычно используется алгоритм Ремеза, чтобы найти оптимальный набор equiripple-коэффициентов.  Задаётся желаемая амплитудно-частотная характеристика, функция весов ошибки отклика и порядок фильтра ''N''.  Затем алгоритм находит множество из &amp;lt;math&amp;gt;\scriptstyle (N \,+\, 1)&amp;lt;/math&amp;gt; коэффициентов, которые минимизируют максимум отклонения от идеального отклика.  Интуитивно понятно, что этот алгоритм находит фильтр, который имеет АЧХ близкую к желаемой с той точностью, которая может быть достигнута с использованием &amp;lt;math&amp;gt;\scriptstyle (N \,+\, 1)&amp;lt;/math&amp;gt; коэффициентов.  Этот метод легко реализуется поскольку по крайней мере одна статья&amp;lt;ref&amp;gt;Rabiner, Lawrence R., and Gold, Bernard, 1975: Theory and Application of Digital Signal Processing (Englewood Cliffs, New Jersey: Prentice-Hall, Inc.)  ISBN 0-13-914101-4&amp;lt;/ref&amp;gt; включает в себя программу, которая принимает требуемую АЧХ и ''N'', и возвращает оптимальные коэффициенты фильтра.&lt;br /&gt;
# Фильтры Чебышева могут быть с тем же успехом построены с использованием алгоритмов БПФ. Алгоритм итеративен по своей природе. Вычисляется ДПФ от начальной характеристики фильтра с помощью БПФ (в качестве начального приближения можно взять h[n]=delta[n]). В частотной области проводится коррекция АЧХ в соответствии со спецификациями и вычисляется ОДПФ. Во временной области оставляют только N коэффициентов(обнулив оставшиеся). Далее повторяют БПФ, коррекцию и т.д.&lt;br /&gt;
&lt;br /&gt;
Программные пакеты такие как MATLAB, GNU Octave, Scilab, и SciPy реализуют описанные выше методы. &lt;br /&gt;
&lt;br /&gt;
Некоторые спецификации на фильтр представляют собой форму входного сигнала во временной области, которую  фильтр должен &amp;quot;распознавать&amp;quot;. Оптимальный согласованный фильтр для выделения сигнала любой формы из белого шума получается путём дискретизации требуемой формы сигнала и использования полученных коэффициентов в обратном порядке в качестве коэффициентов фильтра  — импульсная характеристика полученного фильтра является зеркальным отражением по времени требуемой формы входного сигнала.&lt;br /&gt;
&lt;br /&gt;
=== Построение методом окна ===&lt;br /&gt;
&lt;br /&gt;
В данном методе сначала строится идеальный БИХ-фильтр, затем к нему применяется Функция окна  – во временной области, умножением бесконечной импульсной характеристики на функцию окна. Затем выполняется свёртка полученного результата с откликом на функцию окна. Если идеальная АЧХ достаточно проста, например, как прямоугольный отклик, результат свёртки можно сравнительно легко определить.  На самом деле обычно сначала определяют требуемый результат и решают обратную задачу определения подходящей функции окна.  Для этого метода особенно хорошо подходят окна Кайзера.&lt;br /&gt;
&lt;br /&gt;
== Пример КИХ-фильтра ==&lt;br /&gt;
Примером простого КИХ-фильтра может служить скользящее среднее, используемое для обработки сигналов и изображений, системах автоматического управления и для других прикладных целей. &lt;br /&gt;
Разностное уравнение, которое характеризует фильтр скользящее среднее, является уравнением КИХ-фильтра. Пусть &amp;lt;math&amp;gt;x \left( n \right)&amp;lt;/math&amp;gt; — входной сигнал фильтра, &amp;lt;math&amp;gt;y \left( n \right)&amp;lt;/math&amp;gt; — выходной сигнал. Тогда разностное уравнение будет иметь вид:&lt;br /&gt;
: &amp;lt;math&amp;gt;y \left( n \right) = \sum_{i=0}^{P} b_i x \left( n-i \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Отличительной особенностью скользящего среднего является равенство единице суммы коэффициентов &amp;lt;math&amp;gt;\ b_i &amp;lt;/math&amp;gt;:&lt;br /&gt;
: &amp;lt;math&amp;gt; \sum_{i=0}^{P} b_i = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
Последнее равенство отличает скользящее среднее от любого другого КИХ-фильтра. В частности для простого скользящего среднего:&lt;br /&gt;
: &amp;lt;math&amp;gt;b_{i}=\frac{1}{P+1} &amp;lt;/math&amp;gt; для &amp;lt;math&amp;gt;i=0,1,\dots,P&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того, чтобы найти импульсную переходную функцию скользящего среднего делается следующее допущение:&lt;br /&gt;
: &amp;lt;math&amp;gt;\ x(n) = \delta(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\ \delta(n)&amp;lt;/math&amp;gt; — дельта-функция. Тогда импульсная характеристика такого фильтра может быть записана как:&lt;br /&gt;
: &amp;lt;math&amp;gt;h\left (n\right)=\sum_{i=0}^{P}b_i \delta\left(n-i\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Z-преобразование импульсной характеристики даёт передаточную функцию:&lt;br /&gt;
: &amp;lt;math&amp;gt;H\left(z\right)=\sum_{i=0}^{P}b_i z^{-i}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://www.dsplib.ru/content/filters/fir/fir.html Расчет КИХ фильтра с линейной фазочастотной характеристикой методом частотной выборки]&lt;br /&gt;
* [http://www.dspguru.com/dsp/faqs/fir FIR FAQ]&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80_%D1%81_%D0%BA%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D0%BE%D0%B9_%D0%B8%D0%BC%D0%BF%D1%83%D0%BB%D1%8C%D1%81%D0%BD%D0%BE%D0%B9_%D1%85%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%BE%D0%B9</id>
		<title>Фильтр с конечной импульсной характеристикой</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80_%D1%81_%D0%BA%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D0%BE%D0%B9_%D0%B8%D0%BC%D0%BF%D1%83%D0%BB%D1%8C%D1%81%D0%BD%D0%BE%D0%B9_%D1%85%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%BE%D0%B9"/>
				<updated>2013-07-15T13:59:09Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Фильтр с конечной импульсной характеристикой''' ('''Нерекурсивный фильтр''', '''КИХ-фильтр''') или FIR-фильтр (FIR сокр. от finite impulse response — конечная импульсная характеристика) — один из видов линейных цифровых фильтров, характерной особенностью которого является ограниченность по времени его импульсной характеристики (с какого-то момента времени она становится точно равной нулю). Такой фильтр называют ещё нерекурсивным из-за отсутствия обратной связи. Знаменатель передаточной функции такого фильтра — некая константа.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики ==&lt;br /&gt;
Разностное уравнение, описывающее связь между входным и выходным сигналами фильтра:&lt;br /&gt;
&amp;lt;math&amp;gt;y\left (n\right)=b_0 x\left(n\right)+ b_1 x\left(n-1 \right)+...+b_P x\left(n-P \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; — порядок фильтра, &amp;lt;math&amp;gt;x(n)&amp;lt;/math&amp;gt; — входной сигнал, &amp;lt;math&amp;gt;y(n)&amp;lt;/math&amp;gt; — выходной сигнал, а &amp;lt;math&amp;gt;b_{i}&amp;lt;/math&amp;gt; — коэффициенты фильтра. Иными словами, значение любого отсчета выходного сигнала определяется суммой масштабированных значений &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; предыдущих отсчетов. Можно сказать иначе: значение выхода фильтра в любой момент времени есть значение отклика на мгновенное значение входа и сумма всех постепенно затухающих откликов &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; предыдущих отсчетов сигнала, которые всё ещё оказывают влияние на выход (после &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;-отсчетов импульсная переходная функция становится равной нулю, как уже было сказано, поэтому все члены после &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;-го тоже станут равными нулю). Запишем предыдущее уравнение в более ёмком виде:&lt;br /&gt;
: &amp;lt;math&amp;gt;y \left( n \right) = \sum_{i=0}^{P} b_i x \left( n-i \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
Для того, чтобы найти ядро фильтра положим&lt;br /&gt;
: &amp;lt;math&amp;gt;x(n) = \delta(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;\delta(n)&amp;lt;/math&amp;gt; — дельта-функция. Тогда импульсная характеристика КИХ-фильтра может быть записана как:&lt;br /&gt;
: &amp;lt;math&amp;gt;h\left (n\right)=\sum_{i=0}^{P}b_i \delta\left(n-i\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
Z-преобразование импульсной характеристики даёт нам передаточную функцию КИХ-фильтра:&lt;br /&gt;
: &amp;lt;math&amp;gt;H\left(z\right)=\sum_{i=0}^{P}b_i z^{-i}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства ==&lt;br /&gt;
КИХ-фильтр обладает рядом полезных свойств, из-за которых он иногда более предпочтителен в использовании, чем БИХ-фильтр. Вот некоторые из них:&lt;br /&gt;
* КИХ-фильтры устойчивы.&lt;br /&gt;
* КИХ-фильтры при реализации не требуют наличия обратной связи.&lt;br /&gt;
* Фаза КИХ-фильтров может быть сделана линейной&lt;br /&gt;
&lt;br /&gt;
== Прямая форма КИХ фильтра ==&lt;br /&gt;
КИХ фильтры могут быть реализованы с использованием трех элементов: умножитель, сумматор и блок задержки. Вариант, показанный на рисунке, есть прямая реализация КИХ-фильтров типа 1.&lt;br /&gt;
[[Файл:FIR Filter.png|center|300px|thumb|Реализация прямой формы КИХ фильтра]]&lt;br /&gt;
&lt;br /&gt;
== Пример программы ==&lt;br /&gt;
Ниже приведен пример программы КИХ-фильтра, написанный на C :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 100 // порядок фильтра&lt;br /&gt;
float h[N] = { #include “f1.h” }; //вставка файла с известными коэффициентами фильтра&lt;br /&gt;
float x[N];&lt;br /&gt;
float y[N];&lt;br /&gt;
&lt;br /&gt;
short my_FIR(short sample_data)&lt;br /&gt;
{&lt;br /&gt;
  float result = 0;&lt;br /&gt;
&lt;br /&gt;
  for ( int i = N - 2 ; i &amp;gt;= 0 ; i-- )&lt;br /&gt;
  {&lt;br /&gt;
    x[i + 1] = x[i];&lt;br /&gt;
    y[i + 1] = y[i];&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  x[0] = (float)sample_data;&lt;br /&gt;
  &lt;br /&gt;
  for (int k = 0; k &amp;lt; N; k++)&lt;br /&gt;
  {&lt;br /&gt;
    result = result + x[k]*h[k];&lt;br /&gt;
  }&lt;br /&gt;
  y[0] = result;&lt;br /&gt;
&lt;br /&gt;
  return ((short)result);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Построение КИХ-фильтров ==&lt;br /&gt;
Построение КИХ-фильтров заключается в выборе коэффициентов фильтра таким образом, чтобы полученная система имела требуемые характеристики. Чаще всего фильтр строят по заданной амплитудно-частотной характеристике. Существуют разные методы построения КИХ-фильтров:&lt;br /&gt;
# Построение методом окна&lt;br /&gt;
# Метод частотной выборки&lt;br /&gt;
# Метод наименьших квадратов&lt;br /&gt;
# Метод Паркса-Макклиллана (также известный как Equiripple, Optimal, или Minimax метод).  Алгоритм Ремеза обычно используется, чтобы найти оптимальный набор equiripple-коэффициентов.  Задаётся желаемая амплитудно-частотная характеристика, функция весов ошибки отклика и порядок фильтра ''N''.  Затем алгоритм находит множество из &amp;lt;math&amp;gt;\scriptstyle (N \,+\, 1)&amp;lt;/math&amp;gt; коэффициентов, которые минимизируют максимум отклонения от идеального отклика.  Интуитивно понятно, что этот алгоритм находит фильтр, который имеет АЧХ близкую к желаемой с той точностью, которая может быть достигнута с использованием &amp;lt;math&amp;gt;\scriptstyle (N \,+\, 1)&amp;lt;/math&amp;gt; коэффициентов.  Этот метод легко реализуется поскольку по крайней мере одна статья&amp;lt;ref&amp;gt;Rabiner, Lawrence R., and Gold, Bernard, 1975: Theory and Application of Digital Signal Processing (Englewood Cliffs, New Jersey: Prentice-Hall, Inc.)  ISBN 0-13-914101-4&amp;lt;/ref&amp;gt; включает в себя программу, которая принимает требуемую АЧХ и ''N'', и возвращает оптимальные коэффициенты фильтра.&lt;br /&gt;
# Фильтры Чебышева могут быть с тем же успехом построены с использованием алгоритмов БПФ. Алгоритм итеративен по своей природе. Вычисляется ДПФ от начальной характеристики фильтра с помощью БПФ (в качестве начального приближения можно взять h[n]=delta[n]). В частотной области проводится коррекция АЧХ в соответствии со спецификациями и вычисляется ОДПФ. Во временной области оставляют только N коэффициентов(обнулив оставшиеся). Далее повторяют БПФ, коррекцию и т.д.&lt;br /&gt;
&lt;br /&gt;
Программные пакеты такие как MATLAB, GNU Octave, Scilab, и SciPy реализуют описанные выше методы. &lt;br /&gt;
&lt;br /&gt;
Некоторые спецификации на фильтр представляют собой форму входного сигнала во временной области, которую  фильтр должен &amp;quot;распознавать&amp;quot;. Оптимальный согласованный фильтр для выделения сигнала любой форм из белого шума получается путём дискретизации требуемой формы сигнала и использования полученных коэффициентов в обратном порядке в качестве коэффициентов фильтра  — импульсная характеристика полученного фильтра является зеркальным отражением по времени требуемой формы входного сигнала.&lt;br /&gt;
&lt;br /&gt;
=== Построение методом окна ===&lt;br /&gt;
&lt;br /&gt;
В данном методе сначала строится идеальный БИХ-фильтр, затем к нему применяется Функция окна  – во временной области, умножением бесконечной импульсной характеристики на функцию окна. Затем выполняется свёртка полученного результата с откликом на функцию окна. Если идеальная АЧХ достаточно проста, например, как прямоугольный отклик, результат свёртки можно сравнительно легко определить.  На самом деле обычно сначала определяют требуемый результат и решают обратную задачу определения подходящей функции окна.  Для этого метода особенно хорошо подходят окна Кайзера.&lt;br /&gt;
&lt;br /&gt;
== Пример КИХ-фильтра ==&lt;br /&gt;
Примером простого КИХ-фильтра может служить скользящее среднее, используемое для обработки сигналов и изображений, системах автоматического управления и для других прикладных целей. &lt;br /&gt;
Разностное уравнение, которое характеризует фильтр скользящее среднее, является уравнением КИХ-фильтра. Пусть &amp;lt;math&amp;gt;x \left( n \right)&amp;lt;/math&amp;gt; — входной сигнал фильтра, &amp;lt;math&amp;gt;y \left( n \right)&amp;lt;/math&amp;gt; — выходной сигнал. Тогда разностное уравнение будет иметь вид:&lt;br /&gt;
: &amp;lt;math&amp;gt;y \left( n \right) = \sum_{i=0}^{P} b_i x \left( n-i \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Отличительной особенностью скользящего среднего является равенство единице суммы коэффициентов &amp;lt;math&amp;gt;\ b_i &amp;lt;/math&amp;gt;:&lt;br /&gt;
: &amp;lt;math&amp;gt; \sum_{i=0}^{P} b_i = 1&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
Последнее равенство отличает скользящее среднее от любого другого КИХ-фильтра. В частности для простого скользящего среднего:&lt;br /&gt;
: &amp;lt;math&amp;gt;b_{i}=\frac{1}{P+1} &amp;lt;/math&amp;gt; для &amp;lt;math&amp;gt;i=0,1,\dots,P&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того, чтобы найти импульсную переходную функцию скользящего среднего делается следующее допущение:&lt;br /&gt;
: &amp;lt;math&amp;gt;\ x(n) = \delta(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\ \delta(n)&amp;lt;/math&amp;gt; — [[дельта-функция]]. Тогда импульсная характеристика такого фильтра может быть записана как:&lt;br /&gt;
: &amp;lt;math&amp;gt;h\left (n\right)=\sum_{i=0}^{P}b_i \delta\left(n-i\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Z-преобразование импульсной характеристики даёт передаточную функцию:&lt;br /&gt;
: &amp;lt;math&amp;gt;H\left(z\right)=\sum_{i=0}^{P}b_i z^{-i}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://www.dsplib.ru/content/filters/fir/fir.html Расчет КИХ фильтра с линейной фазочастотной характеристикой методом частотной выборки]&lt;br /&gt;
* [http://www.dspguru.com/dsp/faqs/fir FIR FAQ]&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80_%D1%81_%D0%BA%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D0%BE%D0%B9_%D0%B8%D0%BC%D0%BF%D1%83%D0%BB%D1%8C%D1%81%D0%BD%D0%BE%D0%B9_%D1%85%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%BE%D0%B9</id>
		<title>Фильтр с конечной импульсной характеристикой</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80_%D1%81_%D0%BA%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D0%BE%D0%B9_%D0%B8%D0%BC%D0%BF%D1%83%D0%BB%D1%8C%D1%81%D0%BD%D0%BE%D0%B9_%D1%85%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%BE%D0%B9"/>
				<updated>2013-07-15T13:48:42Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Фильтр с конечной импульсной характеристикой''' ('''Нерекурсивный фильтр''', '''КИХ-фильтр''') или FIR-фильтр (FIR сокр. от finite impulse response — конечная импульсная характеристика) — один из видов линейных цифровых фильтров, характерной особенностью которого является ограниченность по времени его импульсной характеристики (с какого-то момента времени она становится точно равной нулю). Такой фильтр называют ещё нерекурсивным из-за отсутствия обратной связи. Знаменатель передаточной функции такого фильтра — некая константа.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики ==&lt;br /&gt;
Разностное уравнение, описывающее связь между входным и выходным сигналами фильтра:&lt;br /&gt;
&amp;lt;math&amp;gt;y\left (n\right)=b_0 x\left(n\right)+ b_1 x\left(n-1 \right)+...+b_P x\left(n-P \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; — порядок фильтра, &amp;lt;math&amp;gt;x(n)&amp;lt;/math&amp;gt; — входной сигнал, &amp;lt;math&amp;gt;y(n)&amp;lt;/math&amp;gt; — выходной сигнал, а &amp;lt;math&amp;gt;b_{i}&amp;lt;/math&amp;gt; — коэффициенты фильтра. Иными словами, значение любого отсчета выходного сигнала определяется суммой масштабированных значений &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; предыдущих отсчетов. Можно сказать иначе: значение выхода фильтра в любой момент времени есть значение отклика на мгновенное значение входа и сумма всех постепенно затухающих откликов &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; предыдущих отсчетов сигнала, которые всё ещё оказывают влияние на выход (после &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;-отсчетов импульсная переходная функция становится равной нулю, как уже было сказано, поэтому все члены после &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;-го тоже станут равными нулю). Запишем предыдущее уравнение в более ёмком виде:&lt;br /&gt;
: &amp;lt;math&amp;gt;y \left( n \right) = \sum_{i=0}^{P} b_i x \left( n-i \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
Для того, чтобы найти ядро фильтра положим&lt;br /&gt;
: &amp;lt;math&amp;gt;x(n) = \delta(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;\delta(n)&amp;lt;/math&amp;gt; — дельта-функция. Тогда импульсная характеристика КИХ-фильтра может быть записана как:&lt;br /&gt;
: &amp;lt;math&amp;gt;h\left (n\right)=\sum_{i=0}^{P}b_i \delta\left(n-i\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
Z-преобразование импульсной характеристики даёт нам передаточную функцию КИХ-фильтра:&lt;br /&gt;
: &amp;lt;math&amp;gt;H\left(z\right)=\sum_{i=0}^{P}b_i z^{-i}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства ==&lt;br /&gt;
КИХ-фильтр обладает рядом полезных свойств, из-за которых он иногда более предпочтителен в использовании, чем БИХ-фильтр. Вот некоторые из них:&lt;br /&gt;
* КИХ-фильтры устойчивы.&lt;br /&gt;
* КИХ-фильтры при реализации не требуют наличия обратной связи.&lt;br /&gt;
* Фаза КИХ-фильтров может быть сделана линейной&lt;br /&gt;
&lt;br /&gt;
== Прямая форма КИХ фильтра ==&lt;br /&gt;
КИХ фильтры могут быть реализованы с использованием трех элементов: умножитель, сумматор и блок задержки. Вариант, показанный на рисунке, есть прямая реализация КИХ-фильтров типа 1.&lt;br /&gt;
[[Файл:FIR Filter.png|center|300px|thumb|Реализация прямой формы КИХ фильтра]]&lt;br /&gt;
&lt;br /&gt;
== Пример программы ==&lt;br /&gt;
Ниже приведен пример программы КИХ-фильтра, написанный на C :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 100 // порядок фильтра&lt;br /&gt;
float h[N] = { #include “f1.h” }; //вставка файла с известными коэффициентами фильтра&lt;br /&gt;
float x[N];&lt;br /&gt;
float y[N];&lt;br /&gt;
&lt;br /&gt;
short my_FIR(short sample_data)&lt;br /&gt;
{&lt;br /&gt;
  float result = 0;&lt;br /&gt;
&lt;br /&gt;
  for ( int i = N - 2 ; i &amp;gt;= 0 ; i-- )&lt;br /&gt;
  {&lt;br /&gt;
    x[i + 1] = x[i];&lt;br /&gt;
    y[i + 1] = y[i];&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  x[0] = (float)sample_data;&lt;br /&gt;
  &lt;br /&gt;
  for (int k = 0; k &amp;lt; N; k++)&lt;br /&gt;
  {&lt;br /&gt;
    result = result + x[k]*h[k];&lt;br /&gt;
  }&lt;br /&gt;
  y[0] = result;&lt;br /&gt;
&lt;br /&gt;
  return ((short)result);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Построение КИХ-фильтров ==&lt;br /&gt;
Построение КИХ-фильтров заключается в выборе коэффициентов фильтра таким образом, чтобы полученная система имела требуемые характеристики. Чаще всего фильтр строят по заданной амплитудно-частотной характеристике. Существуют разные методы построения КИХ-фильтров:&lt;br /&gt;
# Построение методом окна&lt;br /&gt;
# Метод частотной выборки&lt;br /&gt;
# Метод наименьших квадратов&lt;br /&gt;
# Метод Паркса-Макклиллана (также известный как Equiripple, Optimal, или Minimax метод).  Алгоритм Ремеза обычно используется, чтобы найти оптимальный набор equiripple-коэффициентов.  Задаётся желаемая амплитудно-частотная характеристика, функция весов ошибки отклика и порядок фильтра ''N''.  Затем алгоритм находит множество из &amp;lt;math&amp;gt;\scriptstyle (N \,+\, 1)&amp;lt;/math&amp;gt; коэффициентов, которые минимизируют максимум отклонения от идеального отклика.  Интуитивно понятно, что этот алгоритм находит фильтр, который имеет АЧХ близкую к желаемой с той точностью, которая может быть достигнута с использованием &amp;lt;math&amp;gt;\scriptstyle (N \,+\, 1)&amp;lt;/math&amp;gt; коэффициентов.  Этот метод легко реализуется поскольку по крайней мере одна статья&amp;lt;ref&amp;gt;Rabiner, Lawrence R., and Gold, Bernard, 1975: Theory and Application of Digital Signal Processing (Englewood Cliffs, New Jersey: Prentice-Hall, Inc.)  ISBN 0-13-914101-4&amp;lt;/ref&amp;gt; включает в себя программу, которая принимает требуемую АЧХ и ''N'', и возвращает оптимальные коэффициенты фильтра.&lt;br /&gt;
# Фильтры Чебышева могут быть с тем же успехом построены с использованием алгоритмов БПФ. Алгоритм итеративен по своей природе. Вычисляется ДПФ от начальной характеристики фильтра с помощью БПФ (в качестве начального приближения можно взять h[n]=delta[n]). В частотной области проводится коррекция АЧХ в соответствии со спецификациями и вычисляется ОДПФ. Во временной области оставляют только N коэффициентов(обнулив оставшиеся). Далее повторяют БПФ, коррекцию и т.д.&lt;br /&gt;
&lt;br /&gt;
Программные пакеты такие как MATLAB, GNU Octave, Scilab, и SciPy реализуют описанные выше методы. &lt;br /&gt;
&lt;br /&gt;
Некоторые спецификации на фильтр представляют собой форму входного сигнала во временной области, которую  фильтр должен &amp;quot;распознавать&amp;quot;. Оптимальный согласованный фильтр для выделения сигнала любой форм из белого шума получается путём дискретизации требуемой формы сигнала и использования полученных коэффициентов в обратном порядке в качестве коэффициентов фильтра  — импульсная характеристика полученного фильтра является зеркальным отражением по времени требуемой формы входного сигнала.&lt;br /&gt;
&lt;br /&gt;
=== Построение методом окна ===&lt;br /&gt;
&lt;br /&gt;
В данном методе сначала строится идеальный БИХ-фильтр, затем к нему применяется Функция окна  – во временной области, умножением бесконечной импульсной характеристики на функцию окна. Затем выполняется свёртка полученного результата с откликом на функцию окна. Если идеальная АЧХ достаточно проста, например, как прямоугольный отклик, результат свёртки можно сравнительно легко определить.  На самом деле обычно сначала определяют требуемый результат и решают обратную задачу определения подходящей функции окна.  Для этого метода особенно хорошо подходят окна Кайзера.&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://www.dsplib.ru/content/filters/fir/fir.html Расчет КИХ фильтра с линейной фазочастотной характеристикой методом частотной выборки]&lt;br /&gt;
* [http://www.dspguru.com/dsp/faqs/fir FIR FAQ]&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80_%D1%81_%D0%BA%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D0%BE%D0%B9_%D0%B8%D0%BC%D0%BF%D1%83%D0%BB%D1%8C%D1%81%D0%BD%D0%BE%D0%B9_%D1%85%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%BE%D0%B9</id>
		<title>Фильтр с конечной импульсной характеристикой</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80_%D1%81_%D0%BA%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D0%BE%D0%B9_%D0%B8%D0%BC%D0%BF%D1%83%D0%BB%D1%8C%D1%81%D0%BD%D0%BE%D0%B9_%D1%85%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%BE%D0%B9"/>
				<updated>2013-07-15T13:47:01Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Фильтр с конечной импульсной характеристикой''' ('''Нерекурсивный фильтр''', '''КИХ-фильтр''') или FIR-фильтр (FIR сокр. от finite impulse response — конечная импульсная характеристика) — один из видов линейных цифровых фильтров, характерной особенностью которого является ограниченность по времени его импульсной характеристики (с какого-то момента времени она становится точно равной нулю). Такой фильтр называют ещё нерекурсивным из-за отсутствия обратной связи. Знаменатель передаточной функции такого фильтра — некая константа.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики ==&lt;br /&gt;
Разностное уравнение, описывающее связь между входным и выходным сигналами фильтра:&lt;br /&gt;
&amp;lt;math&amp;gt;y\left (n\right)=b_0 x\left(n\right)+ b_1 x\left(n-1 \right)+...+b_P x\left(n-P \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; — порядок фильтра, &amp;lt;math&amp;gt;x(n)&amp;lt;/math&amp;gt; — входной сигнал, &amp;lt;math&amp;gt;y(n)&amp;lt;/math&amp;gt; — выходной сигнал, а &amp;lt;math&amp;gt;b_{i}&amp;lt;/math&amp;gt; — коэффициенты фильтра. Иными словами, значение любого отсчета выходного сигнала определяется суммой масштабированных значений &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; предыдущих отсчетов. Можно сказать иначе: значение выхода фильтра в любой момент времени есть значение отклика на мгновенное значение входа и сумма всех постепенно затухающих откликов &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; предыдущих отсчетов сигнала, которые всё ещё оказывают влияние на выход (после &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;-отсчетов импульсная переходная функция становится равной нулю, как уже было сказано, поэтому все члены после &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;-го тоже станут равными нулю). Запишем предыдущее уравнение в более ёмком виде:&lt;br /&gt;
: &amp;lt;math&amp;gt;y \left( n \right) = \sum_{i=0}^{P} b_i x \left( n-i \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
Для того, чтобы найти ядро фильтра положим&lt;br /&gt;
: &amp;lt;math&amp;gt;x(n) = \delta(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;\delta(n)&amp;lt;/math&amp;gt; — дельта-функция. Тогда импульсная характеристика КИХ-фильтра может быть записана как:&lt;br /&gt;
: &amp;lt;math&amp;gt;h\left (n\right)=\sum_{i=0}^{P}b_i \delta\left(n-i\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
Z-преобразование импульсной характеристики даёт нам передаточную функцию КИХ-фильтра:&lt;br /&gt;
: &amp;lt;math&amp;gt;H\left(z\right)=\sum_{i=0}^{P}b_i z^{-i}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства ==&lt;br /&gt;
КИХ-фильтр обладает рядом полезных свойств, из-за которых он иногда более предпочтителен в использовании, чем БИХ-фильтр. Вот некоторые из них:&lt;br /&gt;
* КИХ-фильтры устойчивы.&lt;br /&gt;
* КИХ-фильтры при реализации не требуют наличия обратной связи.&lt;br /&gt;
* Фаза КИХ-фильтров может быть сделана линейной&lt;br /&gt;
&lt;br /&gt;
== Прямая форма КИХ фильтра ==&lt;br /&gt;
КИХ фильтры могут быть реализованы с использованием трех элементов: умножитель, сумматор и блок задержки. Вариант, показанный на рисунке, есть прямая реализация КИХ-фильтров типа 1.&lt;br /&gt;
[[Файл:FIR Filter.png|center|300px|thumb|Реализация прямой формы КИХ фильтра]]&lt;br /&gt;
&lt;br /&gt;
== Пример программы ==&lt;br /&gt;
Ниже приведен пример программы КИХ-фильтра, написанный на C :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 100 // порядок фильтра&lt;br /&gt;
float h[N] = { #include “f1.h” }; //вставка файла с известными коэффициентами фильтра&lt;br /&gt;
float x[N];&lt;br /&gt;
float y[N];&lt;br /&gt;
&lt;br /&gt;
short my_FIR(short sample_data)&lt;br /&gt;
{&lt;br /&gt;
  float result = 0;&lt;br /&gt;
&lt;br /&gt;
  for ( int i = N - 2 ; i &amp;gt;= 0 ; i-- )&lt;br /&gt;
  {&lt;br /&gt;
    x[i + 1] = x[i];&lt;br /&gt;
    y[i + 1] = y[i];&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  x[0] = (float)sample_data;&lt;br /&gt;
  &lt;br /&gt;
  for (int k = 0; k &amp;lt; N; k++)&lt;br /&gt;
  {&lt;br /&gt;
    result = result + x[k]*h[k];&lt;br /&gt;
  }&lt;br /&gt;
  y[0] = result;&lt;br /&gt;
&lt;br /&gt;
  return ((short)result);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Построение КИХ-фильтров ==&lt;br /&gt;
Построение КИХ-фильтров заключается в выборе коэффициентов фильтра таким образом, чтобы полученная система имела требуемые характеристики. Чаще всего фильтр строят по заданной амплитудно-частотной характеристике. Существуют разные методы построения КИХ-фильтров:&lt;br /&gt;
# Window design method&lt;br /&gt;
# Метод частотной выборки&lt;br /&gt;
# Метод наименьших квадратов&lt;br /&gt;
# Метод Паркса-Макклиллана (также известный как Equiripple, Optimal, или Minimax метод).  Алгоритм Ремеза обычно используется, чтобы найти оптимальный набор equiripple-коэффициентов.  Задаётся желаемая амплитудно-частотная характеристика, функция весов ошибки отклика и порядок фильтра ''N''.  Затем алгоритм находит множество из &amp;lt;math&amp;gt;\scriptstyle (N \,+\, 1)&amp;lt;/math&amp;gt; коэффициентов, которые минимизируют максимум отклонения от идеального отклика.  Интуитивно понятно, что этот алгоритм находит фильтр, который имеет АЧХ близкую к желаемой с той точностью, которая может быть достигнута с использованием &amp;lt;math&amp;gt;\scriptstyle (N \,+\, 1)&amp;lt;/math&amp;gt; коэффициентов.  Этот метод легко реализуется поскольку по крайней мере одна статья&amp;lt;ref&amp;gt;Rabiner, Lawrence R., and Gold, Bernard, 1975: Theory and Application of Digital Signal Processing (Englewood Cliffs, New Jersey: Prentice-Hall, Inc.)  ISBN 0-13-914101-4&amp;lt;/ref&amp;gt; включает в себя программу, которая принимает требуемую АЧХ и ''N'', и возвращает оптимальные коэффициенты фильтра.&lt;br /&gt;
# Фильтры Чебышева могут быть с тем же успехом построены с использованием алгоритмов БПФ. Алгоритм итеративен по своей природе. Вычисляется ДПФ от начальной характеристики фильтра с помощью БПФ (в качестве начального приближения можно взять h[n]=delta[n]). В частотной области проводится коррекция АЧХ в соответствии со спецификациями и вычисляется ОДПФ. Во временной области оставляют только N коэффициентов(обнулив оставшиеся). Далее повторяют БПФ, коррекцию и т.д.&lt;br /&gt;
&lt;br /&gt;
Программные пакеты такие как MATLAB, GNU Octave, Scilab, и SciPy реализуют описанные выше методы. &lt;br /&gt;
&lt;br /&gt;
Некоторые спецификации на фильтр представляют собой форму входного сигнала во временной области, которую  фильтр должен &amp;quot;распознавать&amp;quot;. Оптимальный согласованный фильтр для выделения сигнала любой форм из белого шума получается путём дискретизации требуемой формы сигнала и использования полученных коэффциентов в обратном порядке в качестве коэффициентов фильтра  — импульсная характеристика полученного фильтра является зеркальным отражением по времени требуемой формы входного сигнала.&lt;br /&gt;
&lt;br /&gt;
=== Window design method ===&lt;br /&gt;
&lt;br /&gt;
В методе Window Design Method сначала строится идеальный БИХ-фильтр, затем к нему применяется Функция окна  – во временной области, умножением бесконечной импульсной характеристики на функцию окна. Затем выполняется свёртка полученного результата с откликом на функцию окна. Если идеальная АЧХ достаточно проста, например, как прямоугольный отклик, результат свёртки можно сравнительно легко определить.  На самом деле обычно сначала определяют требуемый результат и решают обратную задачу определения подходящей функции окна.  Для этого метода особенно хорошо подходят окна Кайзера.&lt;br /&gt;
&lt;br /&gt;
==References==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://www.dsplib.ru/content/filters/fir/fir.html Расчет КИХ фильтра с линейной фазочастотной характеристикой методом частотной выборки]&lt;br /&gt;
* [http://www.dspguru.com/dsp/faqs/fir FIR FAQ]&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80_%D1%81_%D0%BA%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D0%BE%D0%B9_%D0%B8%D0%BC%D0%BF%D1%83%D0%BB%D1%8C%D1%81%D0%BD%D0%BE%D0%B9_%D1%85%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%BE%D0%B9</id>
		<title>Фильтр с конечной импульсной характеристикой</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80_%D1%81_%D0%BA%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D0%BE%D0%B9_%D0%B8%D0%BC%D0%BF%D1%83%D0%BB%D1%8C%D1%81%D0%BD%D0%BE%D0%B9_%D1%85%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%BE%D0%B9"/>
				<updated>2013-07-15T12:44:26Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Фильтр с конечной импульсной характеристикой''' ('''Нерекурсивный фильтр''', '''КИХ-фильтр''') или FIR-фильтр (FIR сокр. от finite impulse response — конечная импульсная характеристика) — один из видов линейных цифровых фильтров, характерной особенностью которого является ограниченность по времени его импульсной характеристики (с какого-то момента времени она становится точно равной нулю). Такой фильтр называют ещё нерекурсивным из-за отсутствия обратной связи. Знаменатель передаточной функции такого фильтра — некая константа.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики ==&lt;br /&gt;
Разностное уравнение, описывающее связь между входным и выходным сигналами фильтра:&lt;br /&gt;
&amp;lt;math&amp;gt;y\left (n\right)=b_0 x\left(n\right)+ b_1 x\left(n-1 \right)+...+b_P x\left(n-P \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; — порядок фильтра, &amp;lt;math&amp;gt;x(n)&amp;lt;/math&amp;gt; — входной сигнал, &amp;lt;math&amp;gt;y(n)&amp;lt;/math&amp;gt; — выходной сигнал, а &amp;lt;math&amp;gt;b_{i}&amp;lt;/math&amp;gt; — коэффициенты фильтра. Иными словами, значение любого отсчета выходного сигнала определяется суммой масштабированных значений &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; предыдущих отсчетов. Можно сказать иначе: значение выхода фильтра в любой момент времени есть значение отклика на мгновенное значение входа и сумма всех постепенно затухающих откликов &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; предыдущих отсчетов сигнала, которые всё ещё оказывают влияние на выход (после &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;-отсчетов импульсная переходная функция становится равной нулю, как уже было сказано, поэтому все члены после &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;-го тоже станут равными нулю). Запишем предыдущее уравнение в более ёмком виде:&lt;br /&gt;
: &amp;lt;math&amp;gt;y \left( n \right) = \sum_{i=0}^{P} b_i x \left( n-i \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
Для того, чтобы найти ядро фильтра положим&lt;br /&gt;
: &amp;lt;math&amp;gt;x(n) = \delta(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;\delta(n)&amp;lt;/math&amp;gt; — дельта-функция. Тогда импульсная характеристика КИХ-фильтра может быть записана как:&lt;br /&gt;
: &amp;lt;math&amp;gt;h\left (n\right)=\sum_{i=0}^{P}b_i \delta\left(n-i\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
Z-преобразование импульсной характеристики даёт нам передаточную функцию КИХ-фильтра:&lt;br /&gt;
: &amp;lt;math&amp;gt;H\left(z\right)=\sum_{i=0}^{P}b_i z^{-i}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства ==&lt;br /&gt;
КИХ-фильтр обладает рядом полезных свойств, из-за которых он иногда более предпочтителен в использовании, чем БИХ-фильтр. Вот некоторые из них:&lt;br /&gt;
* КИХ-фильтры устойчивы.&lt;br /&gt;
* КИХ-фильтры при реализации не требуют наличия обратной связи.&lt;br /&gt;
* Фаза КИХ-фильтров может быть сделана линейной&lt;br /&gt;
&lt;br /&gt;
== Прямая форма КИХ фильтра ==&lt;br /&gt;
КИХ фильтры могут быть реализованы с использованием трех элементов: умножитель, сумматор и блок задержки. Вариант, показанный на рисунке, есть прямая реализация КИХ-фильтров типа 1.&lt;br /&gt;
[[Файл:FIR Filter.png|center|300px|thumb|Реализация прямой формы КИХ фильтра]]&lt;br /&gt;
&lt;br /&gt;
== Пример программы ==&lt;br /&gt;
Ниже приведен пример программы КИХ-фильтра, написанный на C :&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 100 // порядок фильтра&lt;br /&gt;
float h[N] = { #include “f1.h” }; //вставка файла с известными коэффициентами фильтра&lt;br /&gt;
float x[N];&lt;br /&gt;
float y[N];&lt;br /&gt;
&lt;br /&gt;
short my_FIR(short sample_data)&lt;br /&gt;
{&lt;br /&gt;
  float result = 0;&lt;br /&gt;
&lt;br /&gt;
  for ( int i = N - 2 ; i &amp;gt;= 0 ; i-- )&lt;br /&gt;
  {&lt;br /&gt;
    x[i + 1] = x[i];&lt;br /&gt;
    y[i + 1] = y[i];&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  x[0] = (float)sample_data;&lt;br /&gt;
  &lt;br /&gt;
  for (int k = 0; k &amp;lt; N; k++)&lt;br /&gt;
  {&lt;br /&gt;
    result = result + x[k]*h[k];&lt;br /&gt;
  }&lt;br /&gt;
  y[0] = result;&lt;br /&gt;
&lt;br /&gt;
  return ((short)result);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Построение КИХ-фильтров ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://www.dsplib.ru/content/filters/fir/fir.html Расчет КИХ фильтра с линейной фазочастотной характеристикой методом частотной выборки]&lt;br /&gt;
* [http://www.dspguru.com/dsp/faqs/fir FIR FAQ]&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80_%D1%81_%D0%BA%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D0%BE%D0%B9_%D0%B8%D0%BC%D0%BF%D1%83%D0%BB%D1%8C%D1%81%D0%BD%D0%BE%D0%B9_%D1%85%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%BE%D0%B9</id>
		<title>Фильтр с конечной импульсной характеристикой</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A4%D0%B8%D0%BB%D1%8C%D1%82%D1%80_%D1%81_%D0%BA%D0%BE%D0%BD%D0%B5%D1%87%D0%BD%D0%BE%D0%B9_%D0%B8%D0%BC%D0%BF%D1%83%D0%BB%D1%8C%D1%81%D0%BD%D0%BE%D0%B9_%D1%85%D0%B0%D1%80%D0%B0%D0%BA%D1%82%D0%B5%D1%80%D0%B8%D1%81%D1%82%D0%B8%D0%BA%D0%BE%D0%B9"/>
				<updated>2013-07-15T12:34:43Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: Новая страница: «'''Фильтр с конечной импульсной характеристикой''' ('''Нерекурсивный фильтр''', '''КИХ-фильтр'…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Фильтр с конечной импульсной характеристикой''' ('''Нерекурсивный фильтр''', '''КИХ-фильтр''') или FIR-фильтр (FIR сокр. от finite impulse response — конечная импульсная характеристика) — один из видов линейных цифровых фильтров, характерной особенностью которого является ограниченность по времени его импульсной характеристики (с какого-то момента времени она становится точно равной нулю). Такой фильтр называют ещё нерекурсивным из-за отсутствия обратной связи. Знаменатель передаточной функции такого фильтра — некая константа.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики ==&lt;br /&gt;
Разностное уравнение, описывающее связь между входным и выходным сигналами фильтра:&lt;br /&gt;
&amp;lt;math&amp;gt;y\left (n\right)=b_0 x\left(n\right)+ b_1 x\left(n-1 \right)+...+b_P x\left(n-P \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; — порядок фильтра, &amp;lt;math&amp;gt;x(n)&amp;lt;/math&amp;gt; — входной сигнал, &amp;lt;math&amp;gt;y(n)&amp;lt;/math&amp;gt; — выходной сигнал, а &amp;lt;math&amp;gt;b_{i}&amp;lt;/math&amp;gt; — коэффициенты фильтра. Иными словами, значение любого отсчета выходного сигнала определяется суммой масштабированных значений &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; предыдущих отсчетов. Можно сказать иначе: значение выхода фильтра в любой момент времени есть значение отклика на мгновенное значение входа и сумма всех постепенно затухающих откликов &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; предыдущих отсчетов сигнала, которые всё ещё оказывают влияние на выход (после &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;-отсчетов импульсная переходная функция становится равной нулю, как уже было сказано, поэтому все члены после &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt;-го тоже станут равными нулю). Запишем предыдущее уравнение в более ёмком виде:&lt;br /&gt;
: &amp;lt;math&amp;gt;y \left( n \right) = \sum_{i=0}^{P} b_i x \left( n-i \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
Для того, чтобы найти ядро фильтра положим&lt;br /&gt;
: &amp;lt;math&amp;gt;x(n) = \delta(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;\delta(n)&amp;lt;/math&amp;gt; — дельта-функция. Тогда импульсная характеристика КИХ-фильтра может быть записана как:&lt;br /&gt;
: &amp;lt;math&amp;gt;h\left (n\right)=\sum_{i=0}^{P}b_i \delta\left(n-i\right)&amp;lt;/math&amp;gt;&lt;br /&gt;
Z-преобразование импульсной характеристики даёт нам передаточную функцию КИХ-фильтра:&lt;br /&gt;
: &amp;lt;math&amp;gt;H\left(z\right)=\sum_{i=0}^{P}b_i z^{-i}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства ==&lt;br /&gt;
КИХ-фильтр обладает рядом полезных свойств, из-за которых он иногда более предпочтителен в использовании, чем БИХ-фильтр. Вот некоторые из них:&lt;br /&gt;
* КИХ-фильтры устойчивы.&lt;br /&gt;
* КИХ-фильтры при реализации не требуют наличия обратной связи.&lt;br /&gt;
* Фаза КИХ-фильтров может быть сделана линейной&lt;br /&gt;
&lt;br /&gt;
== Прямая форма КИХ фильтра ==&lt;br /&gt;
КИХ фильтры могут быть реализованы с использованием трех элементов: умножитель, сумматор и блок задержки. Вариант, показанный на рисунке, есть прямая реализация КИХ-фильтров типа 1.&lt;br /&gt;
[[Файл:FIR Filter.png|center|300px|thumb|Реализация прямой формы КИХ фильтра]]&lt;br /&gt;
&lt;br /&gt;
== Пример программы ==&lt;br /&gt;
Ниже приведен пример программы КИХ-фильтра, написанный на C :&lt;br /&gt;
&amp;lt;source lang='c'&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define N 100 // порядок фильтра&lt;br /&gt;
float h[N] = { #include “f1.h” }; //вставка файла с известными коэффициентами фильтра&lt;br /&gt;
float x[N];&lt;br /&gt;
float y[N];&lt;br /&gt;
&lt;br /&gt;
short my_FIR(short sample_data)&lt;br /&gt;
{&lt;br /&gt;
  float result = 0;&lt;br /&gt;
&lt;br /&gt;
  for ( int i = N - 2 ; i &amp;gt;= 0 ; i-- )&lt;br /&gt;
  {&lt;br /&gt;
    x[i + 1] = x[i];&lt;br /&gt;
    y[i + 1] = y[i];&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  x[0] = (float)sample_data;&lt;br /&gt;
  &lt;br /&gt;
  for (int k = 0; k &amp;lt; N; k++)&lt;br /&gt;
  {&lt;br /&gt;
    result = result + x[k]*h[k];&lt;br /&gt;
  }&lt;br /&gt;
  y[0] = result;&lt;br /&gt;
&lt;br /&gt;
  return ((short)result);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://www.dsplib.ru/content/filters/fir/fir.html Расчет КИХ фильтра с линейной фазочастотной характеристикой методом частотной выборки]&lt;br /&gt;
* [http://www.dspguru.com/dsp/faqs/fir FIR FAQ]&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A4%D0%B0%D0%B9%D0%BB:FIR_Filter.png</id>
		<title>Файл:FIR Filter.png</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A4%D0%B0%D0%B9%D0%BB:FIR_Filter.png"/>
				<updated>2013-07-15T12:31:41Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: Myachikov загружена новая версия «Файл:FIR Filter.png»: Версия с более низким разрешением&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Реализация прямой формы КИХ фильтра&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	<entry>
		<id>https://vscripts.ru/w/%D0%A4%D0%B0%D0%B9%D0%BB:FIR_Filter.png</id>
		<title>Файл:FIR Filter.png</title>
		<link rel="alternate" type="text/html" href="https://vscripts.ru/w/%D0%A4%D0%B0%D0%B9%D0%BB:FIR_Filter.png"/>
				<updated>2013-07-15T12:30:02Z</updated>
		
		<summary type="html">&lt;p&gt;Myachikov: Реализация прямой формы КИХ фильтра&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Реализация прямой формы КИХ фильтра&lt;/div&gt;</summary>
		<author><name>Myachikov</name></author>	</entry>

	</feed>