BigInteger构造方法问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BigInteger构造方法问题相关的知识,希望对你有一定的参考价值。

BigInteger(int bitLength, int certainty, Random rnd)
构造一个随机生成的正 BigInteger,它可能是一个具有指定 bitLength 的素数。

请问当中的int certainty参数是什么意思?
我要随机生成一个1024位的16进制的素数应该怎么写?

certainty : 调用方允许的不确定性的度量。新的 BigInteger 表示素数的概率超出 (1 - 1/2certainty)。此构造方法的执行时间与此参数的值是成比例的。
就是说生成的数不是绝对是素数 , 是素数的概率是(1 - 1/(2的certainty次幂)) , certainty越大 ,素数概率越大 , 相对的该方法花的时间也越多;
bitlength: 返回的 BigInteger 的 bitLength。这是字节长度 , 4位才能表示一个16进制 , 所以要生成1024位的16进制 , 可以换成4048位的2进制;
new BigInteger(4048 , certainty(该值建议设置100) , new Random());
参考技术A 说实话这参数真的不太好理解,应该是一个概率参数,它用来确保生成的BigInteger是一个素数的概率问题,如果它设置的越大,那么它是素数的概率则越小,文档上说的是1-1/2^certainty。毕竟判断一个大数是否是素数需要很大的计算量,所以你要求的精度越大BigInteger构造所需的时间越长。

仅作参考,不保证理解正确哦本回答被提问者采纳

解析java.math.BigInteger类——构造函数

     最早由于做作业,结识了java的BigInrger类。读着读着,越来越觉得有趣。后来作业做完,也不忍丢下它,索性把全部代码研究一遍。

     开始的时候,一个上午时间最多读懂2个方法。但是还是有滋有味的坚持了下来。下面开始一点点剖开它“隐藏”的秘密。

     首先要想搞懂两个问题:BigIngeter类的目的——实现高精度数的存储和计算。基础的实现机理——用int型(32位)数组存储数据。(在代码的注释中有详细说明)

/////////////////////////////////////////////////////////////

BigInteger类中的属性:{

int signum;    符号位,负数是为-1,零时为0,正数是为1

int[] mag;     The magnitude of this BigInteger,大数的值
//其他辅助变量暂时先不看

}

首先来分析下构造函数 (构造五部曲:1.检查是否符合标准 2.去零 3.mag赋值 4.去mag中零 5.符号位赋值)

1. 使用byte(8位)型数组构造BigInteger:

/////////////////////////////////////////////////////////////////////

 public BigInteger(byte[] val) {
  if (val.length == 0)
     throw new NumberFormatException("Zero length BigInteger"); //传入数组长度为零,报错

  if (val[0] < 0) {
        mag = makePositive(val);
     signum = -1;                 //如果数组第一个值为负数,则将数组变正存入mag,signum赋-1
 } else {
     mag = stripLeadingZeroBytes(val);  //如果非负,则可直接去掉前面无效零,再赋给mag
     signum = (mag.length == 0 ? 0 : 1);

}

}

下面看一下具体调用的函数

///////////////////////////////////////////////////////////////////////////

private static int[] stripLeadingZeroBytes(byte a[]) {
 int byteLength = a.length;
 int keep;

 // Find first nonzero byte
 for (keep=0; keep<a.length && a[keep]==0; keep++)  //找到第一个有效位,并用keep记录下
     ;

 // Allocate new array and copy relevant part of input array
        int intLength = ((byteLength - keep) + 3)/4;   //计算int[]的长度,byte[1/2/3/4]对应int[1]

 int[] result = new int[intLength];
        int b = byteLength - 1;
        for (int i = intLength-1; i >= 0; i--) {
            result[i] = a[b--] & 0xff;           //向int[]赋值,&0xff的作用是消除对int前24位的影响

(计算机中使用补码存储数据,如果直接将一个第一位为“1”的byte值赋给int,则前24为将为“1”)

            int bytesRemaining = b - keep + 1;
            int bytesToTransfer = Math.min(3, bytesRemaining);
            for (int j=8; j <= 8*bytesToTransfer; j += 8)
                result[i] |= ((a[b--] & 0xff) << j);     //进行移位,每次移动8位,再进行或运算
        }
        return result;
    }

 //////////////////////////////////////////////////////////////

  private static int[] makePositive(byte a[]) {
int keep, k;
        int byteLength = a.length;
 
// Find first non-sign (0xff) byte of input
for (keep=0; keep<byteLength && a[keep]==-1; keep++) //找出非符号位(此处我看了很久才看懂)。若a[]=-1,即计算机中二进制为“11111111”,在int型中全为“1”的前几位被认为是符号位。要想转换成正的int值,只需要后几位即可。
   ;
 
        
for (k=keep; k<byteLength && a[k]==0; k++)        //由于传入参数数组第一个值必为负(由构造函数可得),所以不必考虑去零,变量k的作用只是判断需要“额外”位
   ;
 
int extraByte = (k==byteLength) ? 1 : 0;         //如果除符号位以外的全部为“0”,则需要“额外”1位来存储数据
        int intLength = ((byteLength - keep + extraByte) + 3)/4;
int result[] = new int[intLength];
 
        int b = byteLength - 1;
        for (int i = intLength-1; i >= 0; i--) {
            result[i] = a[b--] & 0xff;
            int numBytesToTransfer = Math.min(3, b-keep+1);
            if (numBytesToTransfer < 0)
                numBytesToTransfer = 0;
            for (int j=8; j <= 8*numBytesToTransfer; j += 8)
                result[i] |= ((a[b--] & 0xff) << j);
 
            // Mask indicates which bits must be complemented
            int mask = -1 >>> (8*(3-numBytesToTransfer));  //将负值变为正值,即由原码转反码
            result[i] = ~result[i] & mask;
        }
 
// Add one to one‘s complement to generate two‘s complement
for (int i=result.length-1; i>=0; i--) {
            result[i] = (int)((result[i] & LONG_MASK) + 1);  //long LONG_MASK = 0xffffffffL;为了进行位运算而不考虑int符号问题
   if (result[i] != 0)     //(这个地方也把我蒙骗了好久)突然恍悟,其实就是+1后不为零,即不需要进位,就break退出吧!
                break;
        }
 
return result;
    }
 
2.  使用int(32位)型数组构造BigInteger:
/////////////////////////////////////////////////////////////
private BigInteger(int[] val) {
if (val.length == 0)
   throw new NumberFormatException("Zero length BigInteger");
 
if (val[0] < 0) {
            mag = makePositive(val);
   signum = -1;
} else {
   mag = trustedStripLeadingZeroInts(val);
   signum = (mag.length == 0 ? 0 : 1);
}
    }
 
与byte[]构造原理相同,并且更为简单,不重述。有一点说明,这里使用trustedStripLeadingZeroInts可信赖的去零方法,与StripLeadingZeroInts的区别在于,对于可信赖的去零方法,如果没有无效零,则直接返回原数组,不进行复制。
 
 
转于:http://blog.sina.com.cn/s/blog_6c58b3bf01013wer.html






















以上是关于BigInteger构造方法问题的主要内容,如果未能解决你的问题,请参考以下文章

第1条:考虑用静态工厂方法代替构造器

Java BigInteger类知识点总结

解析java.math.BigInteger类——构造函数

java的BigInteger 类

BigInteger的使用

考虑用静态工厂方法代替构造器的场景