Чтобы иметь возможность использовать сдвиг битов для разделения и рекомбинации, основание должно быть степенью двойки. Использование двух, как в связанном ответе, вероятно, разумно Тогда «длина» входов может быть найдена непосредственно с помощью bitLength
, и разделение может быть реализовано как:
// x = a + 2^N b
BigInteger b = x.shiftRight(N);
BigInteger a = x.subtract(b.shiftLeft(N));
Где N
- это размер, который a
будет иметь в битах.
Учитывая, что BigInteger
реализован с 32-битными конечностями, имеет смысл использовать 2³² в качестве основы, гарантируя, что большие сдвиги включают только перемещение целых чисел, а не более медленный путь кода, где BigInteger
смещено на значение от 1 до 31. Это можно сделать, округлив N
до кратного 32.
Конкретная константа в этой строке,
if (N <= 2000) return x.multiply(y); // optimize this parameter
Вероятно, не следует слишком доверять, учитывая этот комментарий. Для производительности должно быть ограничено некоторые , в противном случае рекурсивное разбиение идет слишком глубоко. Например, когда размер чисел равен 32 или меньше, явно лучше просто умножить, но, вероятно, хорошее отсечение намного выше. В этом источнике самого BigInteger
обрезание выражается через количество конечностей вместо битов и устанавливается равным 80 (так 2560 бит) - у него также есть другой порог, выше которого он переключается 3-х кратное умножение Toom-Cook вместо умножения Карацубы.