<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=3906930</guid>
        <pubDate>Tue, 09 Jul 2024 14:51:46 +0000</pubDate>
        <title>Алгоритм деления двух длинных чисел</title>
        <link>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=3906930</link>
        <description><![CDATA[NuB: <strong class='tag-b'>Dethlord</strong><br>
В конце твоего решения последний пункт, денормализация, это ты что делаешь, просто делишь значения в массиве на scale или там есть ещё какая-то магия известная только тебе? ;)]]></description>
        <author>NuB</author>
        <category>Алгоритмы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1769744</guid>
        <pubDate>Mon, 19 Nov 2007 10:27:10 +0000</pubDate>
        <title>Алгоритм деления двух длинных чисел</title>
        <link>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1769744</link>
        <description><![CDATA[HOMO_PROGRAMMATIS: Мы этому товарищу уже замучились объяснять как же надо делить<br>
<a class='tag-url' href='http://forum.sources.ru/index.php?showtopic=210511&st=0' target='_blank'>Деление двух длинных чисел</a>]]></description>
        <author>HOMO_PROGRAMMATIS</author>
        <category>Алгоритмы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1768891</guid>
        <pubDate>Sun, 18 Nov 2007 17:32:09 +0000</pubDate>
        <title>Алгоритм деления двух длинных чисел</title>
        <link>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1768891</link>
        <description><![CDATA[Dethlord: Я написал подробную схему в чем проблемма то?]]></description>
        <author>Dethlord</author>
        <category>Алгоритмы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1767476</guid>
        <pubDate>Fri, 16 Nov 2007 17:19:10 +0000</pubDate>
        <title>Алгоритм деления двух длинных чисел</title>
        <link>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1767476</link>
        <description><![CDATA[m_fox: делай как на бумажке делишь. длину разряда выбирай произвольно, не важно, бит, байт, слово и т.п.]]></description>
        <author>m_fox</author>
        <category>Алгоритмы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1765247</guid>
        <pubDate>Thu, 15 Nov 2007 07:37:42 +0000</pubDate>
        <title>Алгоритм деления двух длинных чисел</title>
        <link>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1765247</link>
        <description><![CDATA[dm451: Ну тогда может подскажешь... смотри у меня 2 массива, в первом - делимое, во втором - делитель. В каждой ячейке массива по одной цифре. Как реализовать твой метод? Мы же не можем получить полнео число, чтобы потом его перевести в двоичную систему(оно же длинное)...]]></description>
        <author>dm451</author>
        <category>Алгоритмы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1765194</guid>
        <pubDate>Thu, 15 Nov 2007 07:02:19 +0000</pubDate>
        <title>Алгоритм деления двух длинных чисел</title>
        <link>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1765194</link>
        <description><![CDATA[tDCKWL: я си не знаю тока асм]]></description>
        <author>tDCKWL</author>
        <category>Алгоритмы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1765152</guid>
        <pubDate>Thu, 15 Nov 2007 06:33:37 +0000</pubDate>
        <title>Алгоритм деления двух длинных чисел</title>
        <link>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1765152</link>
        <description><![CDATA[dm451: <strong class='tag-b'>Dethlord</strong> спасибо, но не понял, что за код приведен, там не описаны используемые в нем функции.<br>
<strong class='tag-b'>tDCKWL</strong> хороший алгоритм, но чтобы мне его реализовать потребуется очень много времени, а его мало. Не мог бы написать на С? Буду оч. признателен.]]></description>
        <author>dm451</author>
        <category>Алгоритмы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1765102</guid>
        <pubDate>Thu, 15 Nov 2007 05:23:58 +0000</pubDate>
        <title>Алгоритм деления двух длинных чисел</title>
        <link>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1765102</link>
        <description><![CDATA[tDCKWL: в двоичную систему переводишь и делишь столбиком<br>1. выравниваешь делимое и делитель по старшему биту<br>2. вычитаешь из делимого делитель <br>3. если возникает перенос, т.е. делимое меньше, то оставлем его без изменений, -&gt; п.5<br>4. результат пишешь в делимое, в частное + 1<br>5. сдвигаешь в право делитель, влево частное на 1 бит<br>6. делитель не изменился? -&gt; п.2<br>7. теперь в делимом остаток, ставим запятую, если надо делим дальше до нужной точности]]></description>
        <author>tDCKWL</author>
        <category>Алгоритмы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1764969</guid>
        <pubDate>Wed, 14 Nov 2007 21:50:13 +0000</pubDate>
        <title>Алгоритм деления двух длинных чисел</title>
        <link>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1764969</link>
        <description><![CDATA[Dethlord: Совет:<br>
1.Юзать длинную математику<br>
2.Описание алгоритма дано во 2 книге Д Кнута-Целочисленные вычисления <br>
3.Если это очередная контрольная то исходных текстов не ждите тут -разбиритесь сами (вдруг препод смросит :<br>
-а какого типа должны быть переменные хранящие длинные числа <br>
4 У меня есть деления но я писал на VB(школьное деление)<br>
<br>
<br>
Обозначим делитель B=(b0, b1, …, bn-1 ), делимое A=(a0, a1, …, an+m-1), числа имеют длины n и n+m<br>
соответственно.<br>
Общий цикл остается почти таким же: алгоритм состоит из последовательно выполняемых шагов,<br>
где шаг представляет собой деление (n+1)-разрядной части A на n-разрядный делитель<br>
B(исключение может составлять первый шаг, но это укладывается в общую схему, которая будет<br>
обсуждаться ниже).<br>
При этом i-й шаг состоит из двух действий:<br>
1. Угадать i-ю цифру частного q[i]<br>
2. Не создавая временных чисел, вычесть “сдвинутое” произведения B*q[i] из A.<br>
При этом сдвиг B относительно A на каждом шаге уменьшается.<br>
Рассмотрим действия, совершаемые при делении A=68971<br>
на B=513. Здесь n=5, m=2<br>
1. i = (индекс старшего коэффициента A) = 4<br>
a. Угадываем q[0] = 1<br>
b. Вычитаем сдвинутое B*1 = 513 из A<br>
(на бумаге мы при этом пишем только<br>
значимую для следующего шага часть A)<br>
2. i = 3<br>
a. Угадываем q[1] = 3<br>
b. Вычитаем сдвинутое B*3 = 1539 из A<br>
3. i = 2<br>
a. Угадываем q[3] = 4<br>
b. Вычитаем сдвинутое B*4 = 2052 из A<br>
4. i &lt; m = 2, процесс закончен. То, что осталось от A после вычитаний является остатком<br>
деления.<br>
Вроде бы, все очевидно, за исключением одного “творческого” шага – угадывания.<br>
6 8 9 7 1<br>
5 1 3<br>
5 1 3<br>
1 7 6 7<br>
1 5 3 9<br>
2 2 8 1<br>
2 0 5 2<br>
2 2 9<br>
1 3 4<br>
горизонтальные линии проводятся<br>
между шагами<br>
Как заставить компьютер генерировать правильное частное q ? Или, хотя бы, достаточно близкое к<br>
нему число ?<br>
Довольно интересный способ состоит в высказывании догадки qGuess по первым цифрам<br>
делителя и делимого. Понятно, что этих нескольких цифр недостаточно для гарантированно<br>
правильного результата, однако неплохое приближение все же получится.<br>
Пусть очередной шаг представляет собой деление некоторого U = (u0, u1, …, un) на B=(b0, b1, …, bn-<br>
1). Если bn-1 &#8805; BASE/2, то можно доказать следующие факты1.<br>
1. Если положить qGuess = (un*BASE + un-1) / bn-1 , то qGuess-2 &#8804; q &#8804; qGuess.<br>
Иначе говоря, вычисленная таким способом “догадка” будет не меньше искомого частного,<br>
но может быть больше на 1 или 2.<br>
2. Если же дополнительно выполняется неравенство<br>
qGuess*bn-2 &gt; BASE*r + un-2 , где r – остаток при нахождении qGuess и qGuess &#8800; BASE, (2)<br>
то qGuess-1 &#8804; q &#8804; qGuess, причем вероятность события qGuess = q+1 приблизительно равна<br>
2/BASE.<br>
Таким образом, если bn-1 &#8805; BASE/2, то можно вычислить qGuess = (un*BASE + un-1) / bn-1 и<br>
уменьшать на единицу до тех пор, пока не станут выполняться условия (2). Получившееся<br>
значение будет либо правильным частным q, либо, с вероятностью 2/BASE, на единицу большим<br>
числом.<br>
Что делать, если bn-1 слишком мало, чтобы пользоваться таким способом ?<br>
Например, можно домножить делитель и делимое на одно и то же число scale = BASE / ( bn-1 +1 ).<br>
При этом несколько изменится способ вычисления остатка, а частное останется прежним. Такое<br>
домножение иногда называют нормализацией числа.<br>
На тот случай, если qGuess получилось все же на единицу большим q, будем использовать в<br>
пункте (b) вычитание, аналогичное функции Sub, которое вместо отрицательного числа даст<br>
дополнение до следующей степени основания.<br>
Если такое произошло, то последний перенос будет равен borrow = -1. Это сигнал, что необходимо<br>
прибавить одно B назад. Заметим, что в конце сложения будет лишний перенос carry=1, о котором<br>
нужно забыть (он компенсирует borrow=-1).<br>
Например, делим A=505 на B=50. Угаданное частное qGuess=11.<br>
505-550 = 955(=1000-45). Последний перенос borrow=-1, рельное частное q=qGuess-1=10.<br>
Необходимо прибавить одно B: 955+50 = 5.<br>
При сложении произошел перенос carry=1 из старшего разряда. Должно было получится 1005, но<br>
об этом переносе “забыли”, так как он компенсировал borrow=-1.<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// Q = A/B, R=A%B</div><div class="code_line">void Div(const BigInt &amp;A, BigInt &amp;B, BigInt &amp;Q, BigInt &amp;R) {</div><div class="code_line">// Вырожденный случай 1. Делитель больше делимого.</div><div class="code_line">if ( A.Size &#60; B.Size ) {</div><div class="code_line">Q.zero();</div><div class="code_line">R=A;</div><div class="code_line">return;</div><div class="code_line">}</div><div class="code_line">// Вырожденный случай 2. Делитель – число базового типа.</div><div class="code_line">if ( B.Size == 1) {</div><div class="code_line">SDiv ( A, B.Coef[0], Q, R.Coef[0]);</div><div class="code_line">R.Size = 1;</div><div class="code_line">return;</div><div class="code_line">}</div><div class="code_line">1 Доказательства не очень сложны, и если они интересны – они присутствуют в книге Д. Кнута [3].</div><div class="code_line">// Создать временный массив U, равный A</div><div class="code_line">// Максимальный размер U на цифру больше A, с учетом</div><div class="code_line">// возможного удлинения A при нормализации</div><div class="code_line">BigInt U(A.Size+1); U = A; U.Coef[A.Size]=0;</div><div class="code_line">// Указатели для быстрого доступа</div><div class="code_line">short *b=B.Coef, *u=U.Coef, *q=Q.Coef;</div><div class="code_line">long n=B.Size, m=U.Size-B.Size;</div><div class="code_line">long uJ, vJ, i;</div><div class="code_line">long temp1, temp2, temp;</div><div class="code_line">short scale; // коэффициент нормализации</div><div class="code_line">short qGuess, r; // догадка для частного и соответствующий остаток</div><div class="code_line">short borrow, carry; // переносы</div><div class="code_line">// Нормализация</div><div class="code_line">scale = BASE / ( b[n-1] + 1 );</div><div class="code_line">if (scale &#62; 1) {</div><div class="code_line">SMul (U, scale, U);</div><div class="code_line">SMul (B, scale, B);</div><div class="code_line">}</div><div class="code_line">// Главный цикл шагов деления. Каждая итерация дает очередную цифру частного.</div><div class="code_line">// vJ - текущий сдвиг B относительно U, используемый при вычитании,</div><div class="code_line">// по совместительству - индекс очередной цифры частного.</div><div class="code_line">// uJ – индекс текущей цифры U</div><div class="code_line">for (vJ = m, uJ=n+vJ; vJ&#62;=0; --vJ, --uJ) {</div><div class="code_line">qGuess = (u[uJ]*BASE + u[uJ-1]) / b[n-1];</div><div class="code_line">r = (u[uJ]*BASE + u[uJ-1]) % b[n-1];</div><div class="code_line">// Пока не будут выполнены условия (2) уменьшать частное.</div><div class="code_line">while ( r &#60; BASE) {</div><div class="code_line">temp2 = b[n-2]*qGuess;</div><div class="code_line">temp1 = r*BASE + u[uJ-2];</div><div class="code_line">if ( (temp2 &#62; temp1) || (qGuess==BASE) ) {</div><div class="code_line">// условия не выполнены, уменьшить qGuess</div><div class="code_line">// и досчитать новый остаток</div><div class="code_line">--qGuess;</div><div class="code_line">r += b[n-1];</div><div class="code_line">} else break;</div><div class="code_line">}</div><div class="code_line">// Теперь qGuess - правильное частное или на единицу больше q</div><div class="code_line">// Вычесть делитель B, умноженный на qGuess из делимого U,</div><div class="code_line">// начиная с позиции vJ+i</div><div class="code_line">carry = 0; borrow = 0;</div><div class="code_line">short *uShift = u + vJ;</div><div class="code_line">// цикл по цифрам B</div><div class="code_line">for (i=0; i&#60;n;i++) {</div><div class="code_line">// получить в temp цифру произведения B*qGuess</div><div class="code_line">temp1 = b[i]*qGuess + carry;</div><div class="code_line">carry = temp1 / BASE;</div><div class="code_line">temp1 -= carry*BASE;</div><div class="code_line">// Сразу же вычесть из U</div><div class="code_line">temp2 = uShift[i] - temp1 + borrow;</div><div class="code_line">if (temp2 &#60; 0) {</div><div class="code_line">uShift[i] = temp2 + BASE;</div><div class="code_line">borrow = -1;</div><div class="code_line">} else {</div><div class="code_line">uShift[i] = temp2;</div><div class="code_line">borrow = 0;</div><div class="code_line">}</div><div class="code_line">}</div><div class="code_line">// возможно, умноженое на qGuess число B удлинилось.</div><div class="code_line">// Если это так, то после умножения остался</div><div class="code_line">// неиспользованный перенос carry. Вычесть и его тоже.</div><div class="code_line">temp2 = uShift[i] - carry + borrow;</div><div class="code_line">if (temp2 &#60; 0) {</div><div class="code_line">uShift[i] = temp2 + BASE;</div><div class="code_line">borrow = -1;</div><div class="code_line">} else {</div><div class="code_line">uShift[i] = temp2;</div><div class="code_line">borrow = 0;</div><div class="code_line">}</div><div class="code_line">// Прошло ли вычитание нормально ?</div><div class="code_line">if (borrow == 0) { // Да, частное угадано правильно</div><div class="code_line">q[vJ] = qGuess;</div><div class="code_line">} else { // Нет, последний перенос при вычитании borrow = -1,</div><div class="code_line">// значит, qGuess на единицу больше истинного частного</div><div class="code_line">q[vJ] = qGuess-1;</div><div class="code_line">// добавить одно, вычтенное сверх необходимого B к U</div><div class="code_line">carry = 0;</div><div class="code_line">for (i=0; i&#60;n; i++) {</div><div class="code_line">temp = uShift[i] + b[i] + carry;</div><div class="code_line">if (temp &#62;= BASE) {</div><div class="code_line">uShift[i] = temp - BASE;</div><div class="code_line">carry = 1;</div><div class="code_line">} else {</div><div class="code_line">uShift[i] = temp;</div><div class="code_line">carry = 0;</div><div class="code_line">}</div><div class="code_line">}</div><div class="code_line">uShift[i] = uShift[i] + carry - BASE;</div><div class="code_line">}</div><div class="code_line">// Обновим размер U, который после вычитания мог уменьшиться</div><div class="code_line">i = U.Size-1;</div><div class="code_line">while ( (i&#62;0) &amp;&amp; (u[i]==0) ) i--;</div><div class="code_line">U.Size = i+1;</div><div class="code_line">}</div><div class="code_line">// Деление завершено !</div><div class="code_line">// Размер частного равен m+1, но, возможно, первая цифра - ноль.</div><div class="code_line">while ( (m&#62;0) &amp;&amp; (q[m]==0) ) m--;</div><div class="code_line">Q.Size = m+1;</div><div class="code_line">// Если происходило домножение на нормализующий множитель –</div><div class="code_line">// разделить на него. То, что осталось от U – остаток.</div><div class="code_line">if (scale &#62; 1) {</div><div class="code_line">short junk; // почему-то остаток junk всегда будет равен нулю…</div><div class="code_line">SDiv ( B, scale, B, junk);</div><div class="code_line">SDiv ( U, scale, R, junk);</div><div class="code_line">} else R=U;</div><div class="code_line">}</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<br>
<br>
<br>
<br>
<br>
При делении числа длины n на число длины m производится &#920;(n-m) проходов цикла, каждый из<br>
которых делает несколько операций стоимостью &#920; (m). Таким образом, общая оценка будет<br>
квадратичной, как и у умножения: &#920; (nm).]]></description>
        <author>Dethlord</author>
        <category>Алгоритмы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1764952</guid>
        <pubDate>Wed, 14 Nov 2007 21:36:54 +0000</pubDate>
        <title>Алгоритм деления двух длинных чисел</title>
        <link>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1764952</link>
        <description><![CDATA[ZOXEXIVO: Ну ты напиши на листочке 2 числа и подели. и по аналогии делай...]]></description>
        <author>ZOXEXIVO</author>
        <category>Алгоритмы</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1764930</guid>
        <pubDate>Wed, 14 Nov 2007 21:07:28 +0000</pubDate>
        <title>Алгоритм деления двух длинных чисел</title>
        <link>https://forum.sources.ru/index.php?showtopic=210512&amp;view=findpost&amp;p=1764930</link>
        <description><![CDATA[dm451: Здравствуйте, очень нужна помощь знающих людей. У меня задание - написать программу деления 2 длинных чисел на Visual Studio Net(на языке C). Не могу понять, как выполнить деление. ПРочитал кучу инфы, но вопрос остается открытым. Я так понял, чтобы осуществить деление надо, чтобы 2 числа находились в массивах а дальше? <br>Буду очень признателен, если у кого-то есть готовый программный код иолил советы... Спасибо&#33;]]></description>
        <author>dm451</author>
        <category>Алгоритмы</category>
      </item>
	
      </channel>
      </rss>
	