BigInteger的第N个根

时间:2015-06-15 20:48:26

标签: java math biginteger square-root

我正在使用BigInteger对象。使用正常的整数或长整数,我可以使用Math.pow(数字,1 / n根)来获得第n个根。但是,这不适用于BigInteger。有没有办法可以做到这一点?

我实际上并不需要root,只知道它是否是一个完美的力量。 我用这个来弄清楚给定的BigInteger是否是一个完美的方形/立方体等等。

4 个答案:

答案 0 :(得分:2)

牛顿方法与整数完美匹配;假设两个 k,我们计算 s k 不超过 n 的最大数 s n 是积极的:

function iroot(k, n)
    k1 := k - 1
    s := n + 1
    u := n
    while u < s
        s := u
        u := ((u * k1) + n // (u ** k1)) // k
    return s

例如,iroot(4, 624)返回4,iroot(4, 625)返回5.然后您可以执行取幂并检查结果:

function perfectPower(k, n)
    return (k ** iroot(k, n)) == n

例如,perfectPower(2, 625)perfectPower(4, 625)都是正确的,但perfectPower(3, 625)为假。

我会留给你翻译成Java BigInteger。

答案 1 :(得分:1)

您可以使用二进制搜索

  • 很容易实现:
  • x是你的bigint
  • n您要检查的n次方
  • 因此,您要检查y
  • 是否y^n=x
  • 首发假设为x>=0

ALGO:

<强> 1。首先计算y限制ymax

  • 我会使用2^(log2(x)/n)
  • 这是(bits used for x)/n
  • 的数字
  • 因此ymax^nx
  • 的位数相同
  • 首先计算x的位数,然后除以n
  • for (ymax=1,i=1;i<=x;i<<=1) ymax++; ymax=(ymax/n);
  • 现在ymaxy需要测试的位数

<强> 2。 bin搜索

for(m=1<<ymax,y=0;m;m>>=1)
 {
 y|=m;
 if (integer_pow(y,n)>x) y^=m;
 }
return (integer_pow(y,n)==x);
  • integer_pow(y,n)可以通过二进制供电来完成
  • 或使用单个for循环获取小n

第3。添加处理标志

  • 如果(x<0),则n必须明显为奇数,y<0
  • 所以如果没有返回false
  • 否定x以及最终的y结果

[edit1]这里有一些简单的C ++示例:

bool is_root(DWORD &y,DWORD x,DWORD n) // y=x^(1/n) return true if perfect nth root
    {
    DWORD i,p,m; y=x;
    if (n==0) { y=0; return (x==0); }
    if (n==1) { y=x; return (x!=0); }
    for (i=1,m=1;m<x;i++,m<<=1); m=1<<(i/n); // compute the y limit
    for (y=0;m;m>>=1) // bin search through y
        {
        y|=m;
        for (p=y,i=1;i<n;i++) p*=y; // p=y^n
        if (p>x) y^=m; // this is xor not power!!!
        }
    for (p=y,i=1;i<n;i++) p*=y; // p=y^n
    return (p==x);
    }
  • 所以只需将DWORD转换为bigint数据类型
  • 你可以看到你只需要基本的算术和位操作,比如+,<,==,<<,>>,|,^(最后一个是XOR而不是幂)

答案 2 :(得分:0)

我用Newton的公式

解决了这个问题
public boolean perfectPower(BigDecimal a, double n){
    BigDecimal[] x = new BigDecimal[40];
    x[0] = BigDecimal.ONE;
    int digits = a.toString().length();
    System.out.println(digits);
    int roundTo = digits + 1;
    for(int k = 1; k < 40; k++){
        x[k] = (x[k - 1]
                .multiply(BigDecimal.valueOf((int)n - 1))
                .add(a
                        .divide(x[k - 1]
                        .pow((int)n - 1), new MathContext(roundTo, RoundingMode.HALF_EVEN))))
                .multiply(BigDecimal.valueOf(1/n));
    }
    String str = x[39].toString();
    return str.substring(str.indexOf(".") + 1, str.indexOf(".") + 6).equals("00000");
}

答案 3 :(得分:0)

考虑数字并查看有多少不同的因素。如果只有一个,它是一个完美的n次幂,其中n是因子的多重性。可能有更有效的方法,但这可以保证有效。