/** * Use the recursion algorithm to implement the product of two big numbers. * <p> * Assume that we have two binary numbers:u and v. And then we can seperate each * to the higher bits and lower bits.For example, u can be considered as two * parts-- w in high bits and x in low bits. The number v can be also considered * as y in high bits and z in low bits. * <p> * To get the product of uv, you can use this formula: * * <pre> * uv = wy * 2 ^ (n) + (wz + xy) * 2 ^ (n / 2) + xz * </pre> * <p> * Then get the value of wy,wz,xy,xz with recursion until the length of the * number is 1, whose result is itself. We can implement the moveLeft function * to get the value of x * 2^(n). * * @param a * @return the product of this and a. */ public BigNum multiply(BigNum v) { if (this.isZero() || v.isZero()) { returnnewBigNum(1); } if (this.isOne() && v.isOne()) { returnnewBigNum("1"); } BigNumu=this; intlenU= u.getLength(); intlenV= v.getLength(); // BigNum result = new BigNum(lenU + lenV); int hLenU, lLenU; int hLenV, lLenV; if (lenU % 2 == 1) { hLenU = (lenU + 1) / 2; lLenU = (lenU - 1) / 2; } else { hLenU = lenU / 2; lLenU = lenU / 2; }
/** * Add two big numbers with each bit. * * @param a * @return sum */ public BigNum add(BigNum a) { this.trimHead(); a.trimHead(); intlenG= a.getLength() > this.getLength() ? a.getLength() : this.getLength(); // int lenL = a.getLength() < this.getLength() ? a.getLength() : // this.getLength(); BigNumresult=newBigNum(lenG + 1); int i, j, k; intcf=0; i = this.getLength() - 1; j = a.getLength() - 1; k = result.getLength() - 1; while (i >= 0 && j >= 0) { inttmp= cf + this.getInt(i) + a.getInt(j); result.setByte(k, tmp % 2); cf = tmp / 2; i--; j--; k--; } BigNum lagerNum; if (i < 0) { lagerNum = a; i = j; } else { lagerNum = this; } while (i >= 0) { inttmp= cf + lagerNum.getInt(i); result.setByte(k, tmp % 2); cf = tmp / 2; i--; k--; } if (cf != 0) { result.setByte(k, 1); } return result.trimHead(); }
/** * trim the higher zero. * * @return */ public BigNum trimHead() { if (this.isZero()) { returnnewBigNum(1); } intk=0; while (this.getInt(k) == 0) { k++; } intlen=this.getLength() - k; BigNumresult=newBigNum(len); for (inti=0; i < result.getLength(); i++) { result.setByte(i, number[k]); k++; }
return result; }
/** * Clear the low n bits of the number. * * @param n * @return */ public BigNum clearTail(int n) { intlength=this.getLength() - n; if (length == 0) { returnnewBigNum(1); } BigNumresult=newBigNum(length); for (inti=0; i < length; i++) { result.setByte(i, number[i]); } return result.trimHead(); }
/** * Clear the high n bits of the number. * * @param n * @return */ public BigNum clearHead(int n) { intlength=this.getLength() - n; if (length == 0) { returnnewBigNum(1); } BigNumresult=newBigNum(length); for (inti= n, k = 0; i < number.length; i++, k++) { result.setByte(k, number[i]); } return result.trimHead(); }
/** * Imitate the move left operator in binary numbers. * * * @param n digit to move * @return Big number having been moved left */ BigNum moveLeft(int n) { intnewLength= number.length + n; BigNumbigNum=newBigNum(newLength); inti=0; for (i = newLength - 1; i >= (newLength - n); i--) { bigNum.setByte(i, 0); } for (intj=0; j < number.length; j++) { bigNum.setByte(j, number[j]); }
return bigNum.trimHead(); }
publicBigNum(int n) { number = newbyte[n]; for (inti=0; i < number.length; i++) { this.setByte(i, 0); } }
/** * initiate object by String * * @param s */ publicBigNum(String s) { number = newbyte[s.length()];
for (inti=0; i < s.length(); i++) { number[i] = Byte.parseByte(s.substring(i, i + 1)); } }
/** * change number[index] to Integer * * @param index * @return */ publicintgetInt(int index) { return Byte.toUnsignedInt(number[index]); }
publicinttoInteger() { intresult=0; intk=1; for (inti=this.getLength() - 1; i >= 0; i--) { result += this.getInt(i) * k; k *= 2; } return result; }
publicintgetLength() { return number.length; }
publicvoidsetByte(int index, int x) { number[index] = Byte.parseByte(Integer.toString(x)); }
@Override public String toString() { StringBuilderbuilder=newStringBuilder(); for (inti=0; i < number.length; i++) { builder.append(Byte.toString(number[i])); } return builder.toString(); }
publicbooleanisZero() { for (inti=0; i < number.length; i++) { if (this.getInt(i) == 1) { returnfalse; } } returntrue; }
/** * Get a random big binary number * * @param n the digit of the binary number * @return */ publicstatic BigNum getRandomNum(int n) { Randomrandom=newRandom(); StringBuilderbuilder=newStringBuilder(); for (inti=0; i < n; i++) { builder.append(Integer.toString(random.nextInt(2))); } BigNumresult=newBigNum(builder.toString()); return result; }