<?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=140509&amp;view=findpost&amp;p=1124421</guid>
        <pubDate>Sun, 04 Jun 2006 07:34:59 +0000</pubDate>
        <title>Длинная арифметика</title>
        <link>https://forum.sources.ru/index.php?showtopic=140509&amp;view=findpost&amp;p=1124421</link>
        <description><![CDATA[Arsuit: Посмотрел я на свою бывшую статью и ужаснулся... Решил все полностью переписать. Вот гляньте, что я пока написал. Оформлю я все пото, когда допишу все до конца. пока прошу просто посмотреть, почитать, дополнить.<br>
<br>
<span class='tag-size' data-value='14' style='font-size:14pt;'><strong class='tag-b'><span class="tag-color tag-color-named" data-value="blue" style="color: blue">Длинная арифметика</span></strong></span><br>
<br>
Что нужно знать, чтобы понять весь изложенный здесь материал:<br>
1.	Что такое одномерные массивы<br>
2.	Что такое системы счисления, остатки.<br>
3.	Уметь складывать, вычитать, умножать, делить числа столбиком.<br>
<br>
<br>
<strong class='tag-b'>Начальные сведения.</strong><br>
<br>
Когда вы пишите программы на каком либо языке программирования, бывает такое, что стандартных типов данных не хватает, для решения той или иной задачи. Такое бывает, например, если программа использует какой-либо комбинаторный алгоритм, или просто калькулятор длинных чисел.… Здесь уже стандартных типов данных (longint, int64 для паскаля/дельфи и long long для СИ) не хватит. Есть, конечно, типы с плавающей точкой (double, extended), но и их иногда может не хватить…<br>
<br>
Именно для таких случаев существует замечательный способ, который называется длинной арифметикой. Длинная арифметика подразумевает собой хранение длинного числа поразрядно, в одномерном массиве. При том способ хранения может быть разный. Некоторые хранят в одном элементе по одной цифре, другие же хранят в одном элементе  несколько цифр в целях экономии памяти, т. к. процессор выполняет арифметические операции с различными числами за одно и то же время (это относится к сравнительно коротким числам, которые хранятся в стандартных типах). Я предпочитаю хранить несколько цифр (при этом я считаю, что оптимальное число цифр – 4), и ниже будут примеры, реализующие именно этот способ. Но выбирать, чем пользоваться, все же вам. Однако стоит отметить, что в этом способе ЗНАЧИТЕЛЬНО усложняется процедура чтения длинного числа. Кроме всего прочего, число в массиве записывается «задом на перед» - так удобнее. То есть если у меня есть число 123456789012345, и я храню в элементе по 4 цифры, то оно у меня будет выглядеть так:<br>
2345’8901’4567’123.<br>
<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">const </div><div class="code_line">&nbsp;&nbsp;osn=10000; //основание. Так как в элементе массива мы храним 4 цифры, то можно сказать, что оно записано в osn-ичной системе счисления.</div><div class="code_line">&nbsp;&nbsp;max=100; //кол-во элементов массива</div><div class="code_line">type</div><div class="code_line">&nbsp;&nbsp;TLong=array[0..max] of integer; // собственно сам массив с длинным числом.</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<br>
Для удобства в нулевом элементе храним кол-во занятых элементов массива (как в стандартном типе string).<br>
<br>
<br>
<span class='tag-size' data-value='12' style='font-size:12pt;'><strong class='tag-b'>Чтение/вывод</strong></span><br>
<br>
Дальнейшее знакомство с длинными числами наверное стоит начать с процедур чтения/вывода длинного числа. Именно с этого как правило приходится начинать писать длинную арифметику (если конечно эти процедуры вообще нужны). <br>
<br>
<strong class='tag-b'>Чтение.</strong><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">Procedure Long_read(var a:tlong);</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;c:char;</div><div class="code_line">&nbsp;&nbsp;i,j:integer;</div><div class="code_line">&nbsp;&nbsp;a:array[1..100] of byte;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;fillchar(a,sizeof(a),0);</div><div class="code_line">&nbsp;&nbsp;repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp;read(c);</div><div class="code_line">&nbsp;&nbsp;until c in [&#39;0&#39;..&#39;9&#39;];//пропускаем не цифры</div><div class="code_line">&nbsp;&nbsp;i := 1;</div><div class="code_line">&nbsp;&nbsp;while c in [&#39;0&#39;..&#39;9&#39;] do//пока цифры</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;inc(i);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;a[i]:=ord(c)-ord(&#39;0&#39;); //преобразуем символ в цифру</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;read(c); //читаем еще символ.</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp;a[0]:=i;</div><div class="code_line">&nbsp;&nbsp;j := i;</div><div class="code_line">&nbsp;&nbsp;i := 1;</div><div class="code_line">&nbsp;&nbsp;while i&#60;j do //переворачиваем.</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;swap(a[i],a[j]);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;inc(i);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;dec(j);</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">end;</div></ol></div></div></div></div><br>
<br>
Процедура Swap меняет значения переменных. <br>
Если же вы все таки надумали хранить в одном элементе несколько цифр, то алгоритм чтения будет другой. Мы читаем из входного файла по одной цифре начиная с начала массива, и по ходу дела перемещаем все вправо.<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">procedure longread(var a:tlong);</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;c:char;</div><div class="code_line">&nbsp;&nbsp;i:longint;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;fillchar(a,sizeof(a),0); //заполняем массив нулями.</div><div class="code_line">&nbsp;&nbsp;repeat</div><div class="code_line">&nbsp;&nbsp; &nbsp;read(c);</div><div class="code_line">&nbsp;&nbsp;until c in [&#39;0&#39;..&#39;9&#39;]; &nbsp;//пропускаем не символы.</div><div class="code_line">&nbsp;&nbsp;while c in [&#39;0&#39;..&#39;9&#39;] do</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;for i := a[0] downto 1 do &nbsp;//цикл смещения.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;a[i+1]:=a[i+1]+(Longint(a[i])*10) div osn; //добавляем одну цифру из текущего разряда в следующий.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;a[i] := (Longint(a[i])*10) mod osn; //убираем одну цифру из текущего.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;a[1]:=a[1]+ord(c)-ord(&#39;0&#39;); // в конец первого разряда записываем полчтенную цифру.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;if a[a[0]+1]&#62;0 then inc(a[0]); // если мы заняли еще один элемент массива, то увеличиваем нулевой элемент</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;read(c); &nbsp;//читаем очередной символ.</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">end;</div></ol></div></div></div></div><br>
<br>
<br>
P.S. извиняюсь, что так долго пишу - я школу заканчиваю, экзамены, выпускные, поступление на носу...]]></description>
        <author>Arsuit</author>
        <category>Все языки: Статьи, заготовки в FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=140509&amp;view=findpost&amp;p=1089803</guid>
        <pubDate>Wed, 26 Apr 2006 13:28:47 +0000</pubDate>
        <title>Длинная арифметика</title>
        <link>https://forum.sources.ru/index.php?showtopic=140509&amp;view=findpost&amp;p=1089803</link>
        <description><![CDATA[Arsuit: Хорошо, я уже работаю над этим.]]></description>
        <author>Arsuit</author>
        <category>Все языки: Статьи, заготовки в FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=140509&amp;view=findpost&amp;p=1086587</guid>
        <pubDate>Sun, 23 Apr 2006 12:40:08 +0000</pubDate>
        <title>Длинная арифметика</title>
        <link>https://forum.sources.ru/index.php?showtopic=140509&amp;view=findpost&amp;p=1086587</link>
        <description><![CDATA[volvo877: Будут, когда ты это <strong class='tag-b'>оформишь</strong> как следует. В таком виде ничего присоединяться не будет.]]></description>
        <author>volvo877</author>
        <category>Все языки: Статьи, заготовки в FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=140509&amp;view=findpost&amp;p=1086574</guid>
        <pubDate>Sun, 23 Apr 2006 12:30:29 +0000</pubDate>
        <title>Длинная арифметика</title>
        <link>https://forum.sources.ru/index.php?showtopic=140509&amp;view=findpost&amp;p=1086574</link>
        <description><![CDATA[Arsuit: ну так это будут приобщать к общей статье?]]></description>
        <author>Arsuit</author>
        <category>Все языки: Статьи, заготовки в FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=140509&amp;view=findpost&amp;p=1085205</guid>
        <pubDate>Fri, 21 Apr 2006 14:20:40 +0000</pubDate>
        <title>Длинная арифметика</title>
        <link>https://forum.sources.ru/index.php?showtopic=140509&amp;view=findpost&amp;p=1085205</link>
        <description><![CDATA[Arsuit: ну хорошо. начнем с вычитания.<br>
<br>
<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=140509&view=findpost&p=1084235'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Arsuit &#064; <time class="tag-quote__quoted-time" datetime="2006-04-20T17:40:53+00:00">20.04.06, 17:40</time></span><div class='quote '>if a[0]&gt;b[0] then k := a[0] else k := b[0];</div></div> в этой строчке мы в переменную k записываем max(a[0],b[0]) - для границы цикла.<br>
<br>
Затем мы запускаем цикл от 1 до k.<br>
Переменная p служит для того, чтобы мы знали, занимали ли мы из соседнего разряда, или нет. (Если занимали, то p=1, иначе p=0 (все помнят вычитание столбиком?)).<br>
<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=140509&view=findpost&p=1084235'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Arsuit &#064; <time class="tag-quote__quoted-time" datetime="2006-04-20T17:40:53+00:00">20.04.06, 17:40</time></span><div class='quote '>c[i]:=a[i]-b[i]-p;</div></div>Текущему разряду ответа присваиваем разность текущих разрядов вычитаемого и ... ну как его... то, что вычитают. Не помнь я как оно называется. Скажите пожалуйста, кто помнит. Ну так вот. Текущему разряду разности присваиваем разности вичитаемого, то, что вычитают и, если мы из этого разряда занимали, то вычитаем еще и единицу. Затем мы проверяем, если разность получилась отрицательной (if c[i]&lt;0) то занимаем из соседнего разряда, а к текущему разряду ответа прибавляем основание (т. к. он стал отрицатльным).<br>
<br>
и наконец вот эти <div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=140509&view=findpost&p=1084235'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Arsuit &#064; <time class="tag-quote__quoted-time" datetime="2006-04-20T17:40:53+00:00">20.04.06, 17:40</time></span><div class='quote '>for i := k downto 1 do<br>
    if c[i]&lt;&gt;0 then break;<br>
  c[0]:=i;</div></div> строки определяют кол-во цивр в ответе.<br>
Ну вот с вычитанием мы вроде немного разобрались. Теперь деление. (Чтобы понять все, что здесь написано, вы должны помнить, как делятся числа столбиком :) )<br>
<br>
<br>
<div class='tag-quote'><a class='tag-quote-link' href='https://forum.sources.ru/index.php?showtopic=140509&view=findpost&p=1084235'><span class='tag-quote-prefix'>Цитата</span></a> <span class='tag-quote__quote-info'>Arsuit &#064; <time class="tag-quote__quoted-time" datetime="2006-04-20T17:40:53+00:00">20.04.06, 17:40</time></span><div class='quote '>i := 1;<br>
  j := a[0];<br>
  while i&lt;j do<br>
    begin<br>
      swap(a[i],a[j]);<br>
      inc(i);<br>
      dec(j);<br>
    end;</div></div><br>
начнем с этих строк. Они переворачивают делимое. (если кто помнит, в длинной арифметике все числа записаны задом на перед - так с ними удобнее работать, в данном же случае (в случае деления) с длинным числом как раз таки удобнее работать, если оно записано в нормальном виде).<br>
<br>
В переменной ost хранится остаток от деления разряда делимого на делитель. На каждом шаге цикла от 1 до a[0] мы к текущему остатку приписываем цифру из текущего разряда делимого (Longint(ost)*osn+a[i]), и делим все это на делитель (div b) и записываем в разряд частного. А в переменную, хранящую остаток мы записываем остаток от деления (Longint(ost)*osn+a[i]) на делитель.<br>
Все. число поделено.<br>
<br>
<br>
if c[1]=0 then<br>
    begin<br>
      c[0]:=a[0]-1;<br>
      for i := 1 to c[0] do c[i]:=c[i+1];<br>
      c[c[0]+1]:=0;<br>
    end<br>
  else c[0]:=a[0];<br>
если a[1]&lt;b то получится так, что c[1] будет равно 0. Ведущие нули нам не нужны, так что если это так, то сдвигаем все число на разряд влево. А заодно и опредиляем кол-во цифр в ответе.<br>
В конце алгоритма мы переворачиваем число обратно.<br>
<br>
Заметим, что этот алгоритм деления можно несколько усовершенствовать. Можно не переворачивать число, и начать деление с конца. Но выигрыш во времени от этого будет не значительный, а запутаться можно. Так что решайте сами, что вам важнее. <br>
<br>
<span class="tag-color tag-color-named" data-value="gray" style="color: gray"><span class='tag-size' data-value='7' style='font-size:7pt;'>Добавлено <time class="tag-mergetime" datetime="2006-04-21T14:21:29+00:00">21.04.06, 14:21</time></span></span><br>
ну вот. заценивайте статейку.]]></description>
        <author>Arsuit</author>
        <category>Все языки: Статьи, заготовки в FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=140509&amp;view=findpost&amp;p=1084839</guid>
        <pubDate>Fri, 21 Apr 2006 10:14:26 +0000</pubDate>
        <title>Длинная арифметика</title>
        <link>https://forum.sources.ru/index.php?showtopic=140509&amp;view=findpost&amp;p=1084839</link>
        <description><![CDATA[Romtek: А обьяснить принцип? Как ты пришёл к этим процедурам? Это всё желательно показать, т.к. готовых процедур и модулей в интернете полно, а вот нормального описания мало.]]></description>
        <author>Romtek</author>
        <category>Все языки: Статьи, заготовки в FAQ</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=140509&amp;view=findpost&amp;p=1084235</guid>
        <pubDate>Thu, 20 Apr 2006 17:40:53 +0000</pubDate>
        <title>Длинная арифметика</title>
        <link>https://forum.sources.ru/index.php?showtopic=140509&amp;view=findpost&amp;p=1084235</link>
        <description><![CDATA[Arsuit: Недавно решал задачи про длинную арифметику. Написал еще 2 процедуры - это длинное вычитание и деление длинного на короткое. Вот:<br>
<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">procedure longsub(a,b:tlong; var c:tlong);</div><div class="code_line">var k,i,p:longint;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;fillchar(c,sizeof(c),0);</div><div class="code_line">&nbsp;&nbsp;if a[0]&#62;b[0] then k := a[0] else k := b[0];</div><div class="code_line">&nbsp;&nbsp;p := 0;</div><div class="code_line">&nbsp;&nbsp;for i := 1 to k do</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;c[i]:=a[i]-b[i]-p;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;if c[i]&#60;0 then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;p := 1;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;inc(c[i],osn);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;end</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;else p:=0;</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp;for i := k downto 1 do</div><div class="code_line">&nbsp;&nbsp; &nbsp;if c[i]&#60;&#62;0 then break;</div><div class="code_line">&nbsp;&nbsp;c[0]:=i;</div><div class="code_line">end;</div></ol></div></div></div></div><br>
<br>
<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">procedure longdiv(a:tlong; b:longint; var c:tlong);</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;p:longint;</div><div class="code_line">&nbsp;&nbsp;i,j,ost:integer;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;fillchar(c,sizeof(c),0);p:=0;</div><div class="code_line">&nbsp;&nbsp;i := 1;</div><div class="code_line">&nbsp;&nbsp;j := a[0];</div><div class="code_line">&nbsp;&nbsp;while i&#60;j do</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;swap(a[i],a[j]);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;inc(i);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;dec(j);</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp;ost:=0;</div><div class="code_line">&nbsp;&nbsp;for i := 1 to a[0] do</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;c[i]:=(Longint(ost)*osn+a[i])div b;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;ost :=(Longint(ost)*osn+a[i])mod b;</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp;if c[1]=0 then</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;c[0]:=a[0]-1;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;for i := 1 to c[0] do c[i]:=c[i+1];</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;c[c[0]+1]:=0;</div><div class="code_line">&nbsp;&nbsp; &nbsp;end</div><div class="code_line">&nbsp;&nbsp;else c[0]:=a[0];</div><div class="code_line">&nbsp;&nbsp;i := 1;</div><div class="code_line">&nbsp;&nbsp;j := c[0];</div><div class="code_line">&nbsp;&nbsp;while i&#60;j do</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;swap(c[i],c[j]);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;inc(i);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;dec(j);</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">end;</div></ol></div></div></div></div><br>
<br>
<br>
Прошу приобщить все это к основной статье.]]></description>
        <author>Arsuit</author>
        <category>Все языки: Статьи, заготовки в FAQ</category>
      </item>
	
      </channel>
      </rss>
	