Современные информационные технологии/2. Вычислительная техника и программирование

Балгабаева Р.Н.,  Мурадилова Г.С.

Кокшетауский государственный университет им.Ш.Уалиханова, Казахстан

СРАВНЕНИЕ ДЛИННЫХ ЦЕЛЫХ ПРИ РЕАЛИЗАЦИИ АЛГОРИТМОВ НЕСТАНДАРТНОЙ ОБРАБОТКИ ЧИСЕЛ

 

         В языках программирования диапазоны значений базовых числовых типов данных обычно ограничены, и при решении многих задач их оказывается недостаточно. Для повышения точности вычислений, увеличения диапазона или для улучшения какой-нибудь характеристики, разработчики программ сами разрабатывают типы данных для хранения чисел и подпрограммы для арифметических действий с ними.

Рассмотрим некоторые алгоритмы, которые позволяют обрабатывать точные значения неотрицательных целых чисел с большим количеством знаков. Количество знаков зависит от решаемой задачи, ограничений по времени работы программы и ограничений по памяти. Это может быть, например, и сотни десятичных знаков, и тысячи, и более. Обработка этих чисел также зависит от постановки конкретной задачи. В одних задачах к числам нужно применять только аддитивные арифметические операции, в других – только мультипликативные, и т.д.

         Для работы с многоразрядными числами часто разумным оказывается использование массива элементов типа byte, представляющих числа от 0 до 99 (цифры по основанию 100), или типа word (цифры по основанию 10000). По сравнению с хранением одной десятичной цифры в byte, удается приблизительно вдвое сэкономить память, почти не усложнив ввод-вывод. При этом еще и ускоряются некоторые арифметические действия - за счет того, что у числа, записанного в 10000-ричной системе, вчетверо меньше цифр, чем у записанного в десятичной.

При работе с массивом, нужно определить количество его элементов. Часто удобнее представлять длинное целое не просто массивом, а записью, имеющую два поля: целочисленная переменная - количество реально занятых элементов массива и массив.

Чтобы представить длинные целые беззнаковых чисел используем следующую структуру:

const  n = 1000;  const m = 100; const m1=1;

type t1 = 0..n; t2 = 0..m-1;

type BzLong = record

us: t1;

          mas: array [1..n] of  t2;

end;

Количество реально занятых цифр при желании можно разместить не в отдельном поле записи, а в нулевом элементе самого массива (аналогично длине строки в типе string языка Turbo Pascal). Однако это не лучшее решение, поскольку в одном массиве смешиваются величины разной природы. К тому же, записи с несколькими полями позволяют легко менять тип (и, следовательно, диапазон) величин одной природы, не трогая величины другой.

Cравним длинные числа, представленных в типе BzLong. Подпро­грамме передаются два длинных числа (обозначим их l1 и l2). В качестве результата будем возвращать отрицательное число (знак <), положительное (знак >) или нуль (знак =) соответственно ситуациям: первый аргумент меньше, больше или равен второму. Такое решение возвращает больше информации, чем просто "да/нет". Так, в случае, если в некотором алгоритме для каждой из трех ситуаций ll<l2, l1=l2, l1>l2 нужно выполнять свои действия, то достаточно вызвать подпрограмму срав­нения один раз и запомнить результат в целой переменной, которая различает эти три ситуации.

Таким образом, если l1.us<>l2.us, то большее число то, у которого больше цифр. Если же количество цифр обоих чисел равны, то будем сравнивать значения цифр, начиная со старших [больших индексов], пока не наступит одно из двух событий - цифры разные [большее число то, у которого больше цифра] или цифры закончи­лись [числа равны].

     Фрагмент программы сравнения длинных целых чисел представлен в листинге:

   function  fun(const l1,l2:Bzlong): integer;

   var i:t2;

   begin

   if l1.us>l2.us then

               begin

                     fun:=m1; writeln('>') end

              else  if l1.us < l2.us then

                                           begin  fun:=-m1 ; writeln('<');end

                                               else begin

                                                       i:=l1.us;

                                                while (i>=1) and (l1.mas[i]=l2.mas[i]) do

                                                   dec(i);

                                                 if i=0 then

                                                      begin fun:=0;writeln('=') ;end

                                                 else fun:=integer(l1.mas[i])-integer(l2.mas[i]) ;

                               end;

   end;