Я провел некоторое исследование в поисках относительно быстрого алгоритма квадратного корня, который работает с большими целыми числами. Я нашел здесь пару рутин. Первый (ниже) был написан на C...
int isqrt(int n)
{
int b = 0;
while(n >= 0)
{
n = n - b;
b = b + 1;
n = n - b;
}
return b - 1;
}
... которые я нашел здесь: эффективный алгоритм целочисленного квадратного корня для ARM Thumb2
Я реализовал эту процедуру из-за ее простоты и эффективного использования буферного пространства. Однако, как это просто, производительность выходит за рамки неприемлемого. Он работает и дает правильный ответ, когда возвращает только b
, а не b - 1
.
Итак, в поисках лучшего алгоритма я наткнулся на следующий алгоритм, написанный на Java...
public static BigInteger sqrt(BigInteger x) {
BigInteger div = BigInteger.ZERO.setBit(x.bitLength()/2);
BigInteger div2 = div;
// Loop until we hit the same value twice in a row, or wind
// up alternating.
for(;;) {
BigInteger y = div.add(x.divide(div)).shiftRight(1);
if (y.equals(div) || y.equals(div2))
return y;
div2 = div;
div = y;
}
}
... который я нашел по этому вопросу: Как найти квадратный корень из Java BigInteger?
Я с радостью признаю, что я плохо разбираюсь в Java, поэтому вопрос, который у меня есть, заключается в том, что делает строка BigInteger y = div.add(x.divide(div)).shiftRight(1);
?
Насколько я знаю, у меня есть возможное преобразование цикла в приведенный ниже фрагмент кода C, но я недостаточно знаю Java, чтобы быть уверенным.
while (1)
{
x /= div;
div += x;
y = x >> 1;
if (y == div || y == div2) return(y);
div2 = div;
div = y;
}
Это правильно?
BigInteger y = div.add(x.divide(div)).shiftRight(1);
эквивалентен псевдокодуy = (div + x / div) / 2
. - person Rudy Velthuis   schedule 19.07.2016