【问题标题】:Big integers, square root, java and C: What does this line do?大整数、平方根、java 和 C:这条线是做什么的?
【发布时间】:2016-07-19 03:06:20
【问题描述】:

我一直在做一些研究,寻找一种对大整数运算的相对快速的平方根算法。我在这里找到了几个例程。第一个(如下)是用 C 编写的...

int isqrt(int n)
{
  int b = 0;

  while(n >= 0)
  {
    n = n - b;
    b = b + 1;
    n = n - b;
  }

  return b - 1;
}

...我在这里找到的:Looking for an efficient integer square root algorithm for 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;
    }
}

...我在这个问题上找到的:How can I find the Square Root of a 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

标签: java c biginteger sqrt


【解决方案1】:

是的,没错。

让我们翻译吧!

BigInteger y = div.add(x.divide(div)).shiftRight(1);
//becomes
long int y = (div + (x / div)) >> 1;
//this also applies to Java (you don't 'need' BigInteger or its fancy methods)

其余的都很简单。您只是在比较 y 是否等于 div 或 div2,如果不等于,则重新调整值并重试。

【讨论】:

  • 那行得通。谢谢。在查看 C 版本时,它看起来像牛顿的平方根计算方法。使用这种方法,它从大约 92s 到 113us。很大的进步。
  • 我很确定牛顿法。如果你从一个好的猜测开始,而不是1/div,它可能会更快。在我的 BigInteger sqrt() 计算中,我将 div 右移了其位大小的一半作为第一个近似值。当然,使用巨大的 BigInteger 比使用简单的 int 更有意义。
猜你喜欢
  • 2017-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-17
  • 1970-01-01
  • 2017-12-08
  • 2016-01-27
相关资源
最近更新 更多