Опубликован: 21.03.2012 | Доступ: свободный | Студентов: 2948 / 223 | Оценка: 4.44 / 4.19 | Длительность: 06:43:00
Специальности: Программист
Лекция 4:

Задачи "Операции со сверхбольшими числами"

< Лекция 3 || Лекция 4: 12 || Лекция 5 >
Аннотация: Часто на олимпиадах предлагаются задачи, в которых необходимо вычислить результат арифметических операций над сверхбольшими числами. При решении этих задач мы будем опираться на рассмотренные в предыдущей лекции типовые алгоритмы обработки одномерных массивови строк. Цель лекции: научиться производить операции со "сверхбольшими" числами при решении классических задач.

Архитектура 32-х разрядных систем позволяет обрабатывать числа в максимальном диапазоне 0..4294967295. Но это слишком узкий диапазон натуральных чисел для решения многих прикладных задач (см. табл. 3.1).

Справочные сведения:

Таблица 3.1. Форматы целых чисел
Описатель типа Длина(байт) Минимальное число Максимальное число
Integer 2 (со знаком) -32768 +32767
Shortint 1 (со знаком) -128 +127
Longint 4 (со знаком) -2147483648 +2147483647
Byte 1 (без знака) 0 255
Word 2 (без знака) 0 65535

Учиться производить операции со "сверхбольшими" числами будем на практике.

Задача: Найти произведение сверхбольшого числа на цифру.

Идею решения рассмотрим на примере, в котором нужно найти произведение "сверхбольшого" числа 4510905723598 на цифру 3:

  • Вводим число в СТРОКОВУЮ переменную.
  • "РАЗБИРАЕМ" ЧИСЛО НА ЦИФРЫ, помещая каждую цифру в элемент массива:

    4 5 1 0 9 5 7 2 3 5 9 8
  • Умножаем каждый элемент на "3":

    12 15 3 0 27 0 15 21 6 9 15 27 24
  • Организуем перенос: в каждой ячейке оставляем младшую цифру хранящегося там числа, а старшую цифру суммируем с числом, находящимся в левой ячейке:


    Рис. 3.1.

Программа на Бейсике:

input  "введите длинное число"; a$
n = len(a$)
dim a(n), rez(n)
input  "второй сомножитель"; x
for i=1 to n
  a(i)=val(mid$(a$, i, 1))
next
rem=========================
for i=1 to n
  rez(i)=a(i) * x
next
for i=n to 2 step -1
  rem==перенос в старший разряд==
  rez(i - 1) = rez(i - 1) + (rez(i) \ 10)
  rem==остаток в младшем разряде=
  rez(i) = rez(i) mod 10
next
rem====вывод результата==========
for i = 1 to n
  print rez(i);
next

Программа на Паскале:

const 	m=100;
var a, rez: array [1..m] of byte;
  i, n, x, k: integer;
  stroka: string;
begin
  writeln  ('введите длинное число'); readln (stroka);
  n:= length (stroka);
  writeln ('второй сомножитель'); readln (x);
  for i:=1 to n do
    val (copy(stroka, i, 1), a[i], k);
  {==========================}
  for i:=1 to n do
    rez[i]:= a[i] * x;
  for i:=n downto 2 do
    begin
    rez[i - 1]:= rez[i - 1] + rez[i] div 10;
	rez[i]:= rez[i] mod 10;
	end
  {====вывод результата===========}
  for i:=1 to n do
  	write (rez[i]);
end.

Тест:

Дано:

32859305092145

5

Результат: 164296525460725

Задача: Найти сумму двух "сверхбольших" чисел.

Идею решения рассмотрим на примере вычисления суммы двух "сверхбольших" чисел 4510905723569 и 361295487.

Вводим числа в строковые переменные. "РАЗБИРАЕМ" каждое ЧИСЛО НА ЦИФРЫ, помещая цифры в элементы массивов. Массив, в котором будет храниться меньшее число (в примере это массив b) будем заполнять с 5-ой ячейки.


Рис. 3.2.

Массив Sum заполняется суммой соответствующих ячеек массивов А и В. Затем организуем перенос: в каждой ячейке оставляем младшую цифру хранящегося там числа, а старшую цифру суммируем с числом, находящимся в левой ячейке.

Программа на Бейсике:

input "первое слагаемое"; a$
input "второе слагаемое"; b$
n = len(a$)
m = len(b$)
if n > m then max = n else max = m
dim a(max), b(max), sum(max)
rem=========================
for i = 1 to n
  a(i + (max - n)) = val(mid$(a$, i, 1))
next
for i = 1 to m
  b(i + (max - m)) = val(mid$(b$, i, 1))
next
rem=========================
for i = 1 to max
  sum(i) = a(i) + b(i)
next
for i = max to 2 step -1
  sum(i - 1) = sum(i - 1) + sum(i) \ 10
  sum(i) = sum(i) mod 10
next
rem=========================
for i = 1 to max
  print (sum(i));
next
< Лекция 3 || Лекция 4: 12 || Лекция 5 >