Алгоритм деления очень больших чисел

Мне нужно написать алгоритм(я не могу использовать любую стороннюю библиотеку, потому что это назначение), чтобы разделить (целочисленное деление, плавающие части не важны) очень большие числа, такие как 100 - 1000 цифр. Я нашел http://en.wikipedia.org/wiki/Fourier_division алгоритм, но я не знаю, правильный ли это путь. У вас есть предложения?

1) check divisior < dividend, otherwise it's zero (because it will be an int division)
2) start from the left
3) get equal portion of digits from the dividend
4) if it's divisor portion is still bigger, increment digits of dividend portion by 1
5) multiply divisor by 1-9 through the loop
6) when it exceeds the dividend portion, previous multiplier is the answer
7) repeat steps 3 to 5 until reaching to the end

5 ответов


кнут, Дональд, искусство компьютерного программирования, ISBN 0-201-89684-2, Том 2: Полумерные алгоритмы, раздел 4.3.1: классические алгоритмы


Я бы предположил, что разделение "длинного" пути, как в начальной школе, было бы потенциальным маршрутом. Я предполагаю, что вы получаете исходное число в виде строки, поэтому вы анализируете каждую цифру. Пример:

Шаг 0:

   /-----------------
13 | 453453453435....

Шаг 1: "Сколько раз 13 переходит в 4? 0

     0
   /-----------------
13 | 453453453435....

Шаг 2: "Сколько раз 13 переходит в 45? 3

     03
   /-----------------
13 | 453453453435....
   - 39
     --
      6

Шаг 3: "Сколько раз 13 переходит в 63? 4

etc etc. С этой стратегией, вы можете иметь любую длину номера и только действительно иметь достаточно цифр в памяти для int (делителя) и double (дивиденда). (Предполагая, что я правильно понял эти условия). Результат сохраняется как последняя цифра в строке результата.

когда вы попадаете в точку, где не осталось цифр, и расчет не будет идти в 1 или более раз, вы возвращаете свой результат, который уже отформатирован как строка (потому что он может быть потенциально больше, чем int).


самый простой алгоритм деления для реализации больших чисел-сдвиг и вычитание.

if numerator is less than denominator then finish
shift denominator as far left as possible while it is still smaller than numerator
set bit in quotient for amount shifted
subtract shifted denominator from numerator
repeat
the numerator is now the remainder

сдвиг не должен быть буквальным. Например, можно написать алгоритм для вычитания сдвинутого влево значения из другого значения, вместо того чтобы фактически сдвигать все значение, оставшееся до вычитания. То же самое относится и к сравнению.

длинное деление трудно реализовать, потому что один из шагов в длинном делении-длинное деление. Если делитель является int, тогда вы можете сделать длинное деление довольно легко.


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

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

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


Если бы часть вашего задания не была полностью оригинальной, я бы пошел с алгоритмом, который я (и я предполагаю, что вы) преподавали в начальной школе для выполнения большого деления вручную.