Мне нужно сделать следующую арифметику:
long a,b,c;
long result = a*b/c;
Хотя результат гарантированно помещается в long
, умножение - нет, поэтому оно может переполниться.
Я попытался сделать это шаг за шагом (сначала умножить, а затем разделить), имея дело с переполнением, разделив промежуточный результат a*b
на массив int размером не более 4 (так же, как BigInteger использует int[] mag
переменная).
Здесь я застрял с дивизией. Я не могу разобраться с побитовыми сдвигами, необходимыми для точного деления. Все, что мне нужно, это частное (без остатка).
Гипотетический метод будет:
public static long divide(int[] dividend, long divisor)
Кроме того, я не рассматриваю возможность использования BigInteger
, поскольку эта часть кода должна быть быстрой (я бы хотел использовать примитивы и массивы примитивов).
Любая помощь будет высоко ценится!
Edit:
Я не пытаюсь реализовать весь BigInteger
сам. Я пытаюсь решить конкретную проблему (a*b/c
, где a*b
может переполниться) быстрее, чем использование универсального BigInteger
.
Edit2: было бы идеально, если бы это можно было сделать умным 1028 * способом, вообще не допуская переполнения, некоторые комментарии всплыли в комментариях, но я все еще ищу тот, который является правильным.
Обновление:
Я попытался портировать код BigInteger для своих конкретных нужд, без создания объектов, и на первой итерации я получил улучшение скорости на ~ 46% по сравнению с использованием BigInteger (на моем компьютере для разработки).
Затем я попробовал немного модифицированное решение @David Eisenstat, которое дало мне ~ 56% (я выполнил 100_000_000_000 случайных входов от Long.MIN_VALUE
до Long.MAX_VALUE
) сокращенное время выполнения (более чем в 2 раза) по сравнению с BigInteger (то есть ~ 18% по сравнению с моим адаптированным алгоритмом BigInteger).
Будет больше итераций по оптимизации и тестированию, но на данный момент, я думаю, я должен принять этот ответ как лучший.