关闭

JAVA的二进制高精度自然数算法

标签: 高精度算法
303人阅读 评论(0) 收藏 举报

   在8位机和16位机上实现32位计算,在32位机上实现64位和128位计算需要使用一个进位标志寄存器,这个寄存器可以将任意多个内存地址连接成一个整数。但是JAVA上没有办法操作这个寄存器,只能用内存中的一个定义好的变量来作进位。利用这个进位变量,将任意个 int连接,就是所谓的高精度算法了。

  现有的十进制算法效率低,一次只以算一个十进制位,而且浪费内存。我将汇编语言的算法用于JAVA,写的这个高精度无符号整数,一次可以算9个十进制位,省内存。也可以轻松改装成有符号的数。它与原始类型int,long是相似的,可以做位运算。


  注意,因为是仿汇编的算法,所以在加法和乘法时,可能会发生高位截断。为防止高位截断,请在计算前把被加数或被乘数的精度设为所需要的最大精度。而计算完后,如果有很大概率不需要使用过高的精度,则可以使用Trim()来自适应地减小精度。


  需要负数的朋友请用DEG()函数。需要显示负数时,用NEG()将已判定为负的数反转成绝对值显示,左边自己加个负号。需要输入负数时,将绝对值部分输入,再用NEG()取补码。如果不喜欢汇编式的算法,可以自己写一个类,增加一个表示符号的成员变量,扩展运算方法。需要扩展:加、减、乘、除、余数,增加算术右移指令。


  例程(使用方法):

package sample.razerpen.math;


import psn.razerpen.math.SuperInteger;


public class TestSuperInteger {

public static void main(String[] args) {
SuperInteger si=new SuperInteger("9876543210545465468464946464645");//随便写个数字

SuperInteger si2=new SuperInteger(si);//复制,也可以直接写个不一样或一样的数字
Print(si);//显示
Print(si2);//显示
si.mod(si2);//余数
Print(si);//显示结果,计算结果是存储在被除数里的,这一点和汇编一样。如果同时需要商和余数,最好使用DivAndMod这个方法,因为DIV()和MOD()方法都是用这个方法实现的。


}

private static void Print(SuperInteger si){
System.out.println(si+"\t"+si.toBinaryString());
}

}

  高精度类:

package psn.razerpen.math;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;


/**
 * 无符号高精度整数,自然数。有BUG请发给我的邮箱,谢谢。
 * @author Razerpen
 * @E-mail rediculous@163.com
 * 2015-07-10
 */
public class SuperInteger implements Comparable<SuperInteger> , Serializable {

/**

*/
private static final long serialVersionUID = 1L;

/**
* 高精度的10,精度为1
*/
static public final SuperInteger CONST_SUPERINTEGER_10=new SuperInteger(new int []{10});
/**
* 高精度的1,精度为1
*/
static public final SuperInteger CONST_SUPERINTEGER_1=new SuperInteger(new int []{1});
/**
* 高精度的0,精度为0
*/
static public final SuperInteger CONST_SUPERINTEGER_0=new SuperInteger(new int []{});

/**
* 数字串,低位在低索引,高位在高索引
*/
private List<Integer> m_data=new ArrayList<Integer>();

/**
* 空构造函数,造成数据为0,精度为0
*/
public SuperInteger(){

}

/**

* @param is 导入的数据,低位在低索引,高位在高索引
*/
public SuperInteger(int[] is) {
SetValue(is);
}

/**
* 复制一个高精度整数
* @param value
*/
public SuperInteger(SuperInteger value) {
SetValue(value);
}

/**
* 用字符串输入数字,按正常书写顺序,非数字字符被忽略。输入无数字的字符串则得到一个精度为0的高精度数字0。高位多余的0有可能会被忽略,最多可存在31个连续的高位0
* @param value
*/
public SuperInteger(String value){
SetValue(value);
}

@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return new SuperInteger(this);
}


/**
* 返回精度,以int值个数表示。
* @return 
*/
public int GetPrecision(){
return m_data.size();
}

/**
* 返回精度,以二进制位个数表示
* @return 
*/
public int GetBitsPrecision(){
return GetPrecision()*Integer.SIZE;
}

/**
* 设定精度,以int个数表示
* @param precision int个数
* @return this
*/
public SuperInteger SetPrecision(int precision){
if(precision>m_data.size()){
for(int i=m_data.size();i<precision;++i){
m_data.add(0);
}
}else{
for(int i=m_data.size()-1;i>=precision;--i){
m_data.remove(m_data.size()-1);
}
}
return this;
}

/**
* 去除高位的 0 int值,节省存储空间
* @return this
*/
public SuperInteger Trim(){
int last=0;
for(;;){
last=m_data.size()-1;
if(last<0){
m_data.clear();
break;
}
if(m_data.get(last)!=0){
break;
}
m_data.remove(last);
}
return this;
}

/**
* 复制一个自然数
* @param value
* @return
*/
public SuperInteger SetValue(SuperInteger value){
m_data.clear();
return CopyValue(value, true);
}


/**
* 设置自然数值,低位在低索引,高低在高索引
* @param value
* @return
*/
public SuperInteger SetValue(int[] value) {
m_data.clear();
int nSize=value.length;
for(int i=0;i<nSize;++i){
m_data.add(value[i]);
}
return this;
}


/**
* 设置自然数值,低位在低索引,高低在高索引
* @param value
* @return
*/
public SuperInteger SetValue(List<Integer> value){
m_data.clear();
int nSize=value.size();
for(int i=0;i<nSize;++i){
m_data.add(value.get(i));
}
return this;
}

/**
* 设置自然数值,按正常书写方式
* @param value
* @return
*/
public SuperInteger SetValue(String value){
StringBuffer sb=new StringBuffer();
for(int i=value.length();i-->0;){
if(value.charAt(i)<='9') if(value.charAt(i)>='0'){
sb.append(value.charAt(i));
}
}
value=sb.toString();

m_data.clear();
SetPrecision((value.length()+8)/9);
SuperInteger level=new SuperInteger(CONST_SUPERINTEGER_1).SetPrecision(GetPrecision());
SuperInteger num=new SuperInteger().SetPrecision(GetPrecision());

for(int i=0;i<value.length();++i){
SuperInteger num_t=new SuperInteger(new int [] {value.charAt(i)-'0'}).SetPrecision(level.GetPrecision());
num.CopyValue(num_t, false);
num.MUL(level);
ADD(num);
level.MUL(CONST_SUPERINTEGER_10);
}

Trim();
return this;
}

/**
* 取得自然数存储容器
* @return
*/
public List<Integer> GetValue(){
return m_data;
}

/**
* 设置指定的int位
* @param index 索引
* @param value 值
* @param bAutoExtension true 如果位不存在,则扩展该自然数的精度 false 如果位不存在,则不做处理
* @return
*/
public SuperInteger SetInt(int index,int value,boolean bAutoExtension){
if(index<m_data.size()){
m_data.set(index, value);
}else{
if(bAutoExtension){
SetPrecision(index);
m_data.add(value);
}
}
return this;
}


/**
* 取得指定的int位,位不存在则返回0
* @param index
* @return
*/
public int GetInt(int index){
if(index<m_data.size())return m_data.get(index);
return 0;
}

/**
* 设置指定的二进制位 
* @param index
* @param bAutoExtension true 如果位不存在,则扩展该自然数的精度 false 如果位不存在,则不做处理
*/
public SuperInteger SetBit(int index,boolean bValue,boolean bAutoExtension){
int i_i=IntIndex(index),i_b=index=BitIndex(index);
int i=GetInt(i_i);
if(bValue) i|=OrBitInInt(i_b);
else i&=AndBitInInt(i_b);
SetInt(i_i, i, bAutoExtension);
return this;
}


/**
* 取得指定的二进制位,不存在则返回false
* @param index
* @return true 1 false 0
*/
public boolean GetBit(int index){
int i_i=IntIndex(index),i_b=index=BitIndex(index);
int i=GetInt(i_i);
return (i&(1<<i_b))!=0;
}

/**
* 复制另一个自然数,而不降低自身的精度。若被复制方精度更高,则高位被忽略,若被复制方精度更低,则高位以0代替
* @param value
* @param bAutoExtension true 如果位不存在,则扩展该自然数的精度 false 如果位不存在,则不做处理
* @return
*/
public SuperInteger CopyValue(SuperInteger value,boolean bAutoExtension){
if(bAutoExtension){
if(GetPrecision()<value.GetPrecision()){
SetPrecision(value.GetPrecision());
}
}
for(int i=GetPrecision();i-->0;){
SetInt(i, value.GetInt(i), false);
}
return this;
}


/**
* 逻辑左移位
* @param si
* @return
*/
public SuperInteger shl(SuperInteger si){return SHL(si);}

/**
* 逻辑左移位
* @param si
* @return
*/
public SuperInteger SHL(SuperInteger si) {
return SHL(si.GetInt(0));
}


/**
* 逻辑左移位
* @param nShlTimes
* @return
*/
public SuperInteger shl(int nShlTimes){return SHL(nShlTimes);}

/**
* 逻辑左移位
* @param nShlTimes
* @return
*/
public SuperInteger SHL(int nShlTimes){
if(nShlTimes<0){
SHR(-nShlTimes);
return this;
}
SHLIntegers(IntIndex(nShlTimes));
SHLEachInteger(BitIndex(nShlTimes));
return this;
}


/**
* 逻辑右移位
* @param si(仅最低的一个int有效)
* @return
*/
public SuperInteger shr(SuperInteger si){return SHR(si);} 

/**
* 逻辑右移位
* @param si(仅最低的一个int有效)
* @return
*/
public SuperInteger SHR(SuperInteger si) {
return SHR(si.GetInt(0));
}


/**
* 逻辑右移位
* @param nShrTimes
* @return
*/
public SuperInteger shr(int nShrTimes){return SHR(nShrTimes);}

/**
* 逻辑右移位
* @param nShrTimes
* @return
*/
public SuperInteger SHR(int nShrTimes){
if(nShrTimes<0){
SHL(-nShrTimes);
return this;
}
SHRIntegers(IntIndex(nShrTimes));
SHREachInteger(BitIndex(nShrTimes));
return this;
}

/**
* 按位取反
* @return
*/
public SuperInteger not(){return NOT();}

/**
* 按位取反
* @return
*/
public SuperInteger NOT(){
for(int i=m_data.size();i-->0;){
SetInt(i,~GetInt(i),false);
}
return this;
}

/**
* 位与
* @param si
* @return
*/
public SuperInteger and(SuperInteger si){return AND(si);}

/**
* 位与
* @param si
* @return
*/
public SuperInteger AND(SuperInteger si){
for(int i=m_data.size();i-->0;){
SetInt(i,GetInt(i)&si.GetInt(i),false);
}
return this;
}

/**
* 位或
* @param si
* @return
*/
public SuperInteger or(SuperInteger si){return OR(si);}

/**
* 位或
* @param si
* @return
*/
public SuperInteger OR(SuperInteger si){
for(int i=m_data.size();i-->0;){
SetInt(i,GetInt(i)|si.GetInt(i),false);
}
return this;
}

/**
* 位异或
* @param si
* @return
*/
public SuperInteger xor(SuperInteger si){return XOR(si);}

/**
* 位异或
* @param si
* @return
*/
public SuperInteger XOR(SuperInteger si){
for(int i=m_data.size();i-->0;){
SetInt(i,GetInt(i)^si.GetInt(i),false);
}
return this;
}

/**
* 位同或
* @param si
* @return
*/
public SuperIntegerwor(SuperInteger si){return WOR(si);}

/**
* 位同或
* @param si
* @return
*/
public SuperIntegerWOR(SuperInteger si){
for(int i=m_data.size();i-->0;){
SetInt(i,~(GetInt(i)^si.GetInt(i)),false);
}
return this;
}

/**
* 变补码(等价于负数的正整数码)
* @return
*/
public SuperInteger neg(){return NEG();}

/**
* 变补码(等价于负数的正整数码)
* @return
*/
public SuperInteger NEG(){
NOT();
ADD(CONST_SUPERINTEGER_1);
return this;
}


/**
* 加法,高位截断
* @param a
* @return
*/
public SuperInteger add(SuperInteger a){return ADD(a);}

/**
* 加法,高位截断
* @param a
* @return
*/
public SuperInteger ADD(SuperInteger a){
int nSize=Math.max(m_data.size(), a.m_data.size());
int nC=0;
for(int i=0;i<nSize;++i){
int i1=GetInt(i);
int i2=a.GetInt(i);
int sum=i1+i2+nC;
nC=Carry(i1,i2,sum);
SetInt(i,sum,false);
}
return this;
}


/**
* 减法
* @param a
* @return
*/
public SuperInteger sub(SuperInteger a){return SUB(a);}

/**
* 减法
* @param a
* @return
*/
public SuperInteger SUB(SuperInteger a){
SuperInteger t=NewTempInteger(a);
ADD(t.DEG());
return this;
}


/**
* 乘法,高位截断
* @param a
* @return
*/
public SuperInteger mul(SuperInteger a){return MUL(a);}

/**
* 乘法,高位截断
* @param a
* @return
*/
public SuperInteger MUL(SuperInteger a){
SuperInteger t=NewTempInteger(a);
SuperInteger ans=new SuperInteger().SetPrecision(GetPrecision());
int p=GetBitsPrecision();
int nSh_t=0;
for(int i=0;i<p;++i){
if(GetBit(i)){
t.SHL(nSh_t);
ans.ADD(t);
nSh_t=1;
}else{
++nSh_t;
}
}
this.m_data=ans.m_data;
return this;
}

/**
* 除法,除不尽,有余数
* @param a
* @return
*/
public SuperInteger div(SuperInteger a){return DIV(a);}

/**
* 除法,除不尽,有余数
* @param a
* @return
*/
public SuperInteger DIV(SuperInteger a){
DivAndMod(this, null, this, a);
return this;
}

/**
* 余数
* @param a
* @return
*/
public SuperInteger mod(SuperInteger a){return MOD(a);}

/**
* 余数
* @param a
* @return
*/
public SuperInteger MOD(SuperInteger a){
DivAndMod(null, this, this, a);
return this;
}

/**
* 同时计算商和余数的除法
* @param div 商
* @param mod 余数
* @param a 被除数
* @param b 除数
*/
public static void DivAndMod(SuperInteger div,SuperInteger mod,SuperInteger a,SuperInteger b){
if(b.IsZero()){
System.out.println("计算错误:除数为0");
return ;
}
if(div==mod){
System.out.println("无法计算:除数和余数使用了相同的引用");
return ;
}
int precision=0;
if(mod==null){
mod=new SuperInteger();
precision=1;
}
if(div==null){
if(precision==1){
System.out.println("没有任何接收对象");
return;
}
div=new SuperInteger();
}
precision=div.GetPrecision();
precision=Math.max(precision, mod.GetPrecision());
precision=Math.max(precision, a.GetPrecision());
precision=Math.max(precision, b.GetPrecision());


SuperInteger t1=NewTempInteger(a,precision);
SuperInteger t2=NewTempInteger(b,precision);

mod.CopyValue(CONST_SUPERINTEGER_0, false);
div.CopyValue(CONST_SUPERINTEGER_0, false);

int i=t2.GetBitsPrecision()-1;
for(;i>=0;--i){
if(t2.GetBit(i))break;
}
int j=t2.GetBitsPrecision()-i-1;
t2.SHL(j);
SuperInteger t_ans=new SuperInteger(new int[]{1}).SetPrecision(precision);
t_ans.SHL(j);

int nSh_t=0;
for(i=j;i>=0;--i){
if(t2.compareTo(t1)<=0){
t_ans.SHR(nSh_t);
t1.SUB(t2);
div.ADD(t_ans);
nSh_t=1;
}else{
nSh_t+=1;
}
t2.SHR(1);
}

// while(!t_ans.IsZero()){
// if(t2.compareTo(t1)<=0){
// t1.SUB(t2);
// div.ADD(t_ans);
// }
// t2.SHR(1);
// t_ans.SHR(1);
// nSh_t+=1;
// }

mod.CopyValue(t1, false);

}

/**
* 为0返回true,有两种情况的0值,所有int位都为0,精度为0。
* @return
*/
public boolean IsZero() {
if(m_data.isEmpty())return true;
for(int i:m_data){
if(i!=0)return false;
}
return true;
}


@Override
public boolean equals(Object obj) {
if(obj==null)return false;
if(obj.getClass()!=SuperInteger.class)return false;
return 0==compareTo((SuperInteger)obj);
}


/**
* this更大,或者o为空返回正
* 数值上一样大(精度可能不一样),返回0
* this更小,返回负
*/
@Override
public int compareTo(SuperInteger o) {
if(o==null)return 1;
int nSize=Math.max(GetPrecision(), o.GetPrecision());
for(int i=nSize;i-->0;){
int a=GetInt(i),b=o.GetInt(i);
if(a>=0){
if(b>=0){
int comp=a-b;
if(comp!=0)return comp;
}else{
return -1;
}
}else{
if(b>=0){
return 1;
}else{
int comp=a-b;
if(comp!=0)return comp;
}
}
}
return 0;
}


/**
* 十进制数字字符串
*/
@Override
public String toString() {
if(IsZero())return "0";
StringBuffer sb=new StringBuffer();
List<Character> charList=new LinkedList<Character>();
SuperInteger si=new SuperInteger(this);
SuperInteger mod=new SuperInteger(new int []{0});
while(!si.IsZero()){
DivAndMod(si, mod, si, CONST_SUPERINTEGER_10);
char c=(char) (mod.m_data.get(0)+'0');
charList.add(c);
}
for(int i=charList.size();i-->0;){
sb.append(charList.get(i));
}
return sb.toString();
}


/**
* 二进制数字字符串
* @return
*/
public String toBinaryString(){return toBinaryString(" ");}

/**
* 二进制数字字符串
* @param separator 每个int位间的分隔符
* @return
*/
public String toBinaryString(String separator){
StringBuffer sb=new StringBuffer();
for(int i=m_data.size();i-->0;){
StringBuffer sb1=new StringBuffer();
for(int j=0;j<32;++j){
sb1.append('0');
}
StringBuffer sb2=new StringBuffer(Integer.toBinaryString(m_data.get(i)));
int i1=sb1.length();
int i0=i1-sb2.length();
sb1.replace(i0, i1, sb2.toString());
sb.append(sb1);
sb.append(separator);
}
return sb.toString();
}

private SuperInteger NewTempInteger(SuperInteger a){
return NewTempInteger(a, GetPrecision());
}


private static SuperInteger NewTempInteger(SuperInteger a,int precision) {
SuperInteger t=new SuperInteger(a);
t.SetPrecision(precision);
return t;
}


private int Carry(int i1, int i2, int sum) {
if(i1>=0){
if(i2>=0){
return 0;
}else{
if(sum>=0)return 1;
else return 0;
}
}else{
if(i2>=0){
if(sum>=0)return 1;
else return 0;
}else{
return 1;
}
}
}


private int SHLEachInteger(int nShlTimes){
if(nShlTimes<0)return SHREachInteger(-nShlTimes);
nShlTimes=BitIndex(nShlTimes);
if(nShlTimes==0)return 0;
int nShl=0;
int nDataSize=m_data.size();
for(int i=0;i<nDataSize;++i){
int nShl_temp=nShl;
int nCurrentInt=m_data.get(i);
int nRestBits=Integer.SIZE-nShlTimes;

nShl=SHRInteger(nCurrentInt, nRestBits);

nCurrentInt=SHLInteger(nCurrentInt, nShlTimes);
nCurrentInt|=nShl_temp;

m_data.set(i, nCurrentInt);
}
return nShl;
}

private int SHREachInteger(int nShrTimes){
if(nShrTimes<0)return SHLEachInteger(-nShrTimes);
nShrTimes=BitIndex(nShrTimes);
if(nShrTimes==0)return 0;
int nShr=0;
int nDataSize=m_data.size();
for(int i=nDataSize-1;i>=0;--i){
int nShr_temp=nShr;
int nCurrentInt=m_data.get(i);
int nRestBits=Integer.SIZE-nShrTimes;

nShr=SHLInteger(nCurrentInt, nRestBits);

nCurrentInt=SHRInteger(nCurrentInt, nShrTimes);
nCurrentInt|=nShr_temp;

m_data.set(i, nCurrentInt);
}
return nShr;
}

private void SHLIntegers(int nShlTimes){
int nDataSize=m_data.size();
if(nShlTimes>=nDataSize){
for(int i=0;i<nDataSize;++i){
m_data.set(i, 0);
}
return;
}
if(nShlTimes<0){
SHRIntegers(-nShlTimes);
return;
}
int i;
for(i=nDataSize-1;i>=nShlTimes;--i){
m_data.set(i, m_data.get(i-nShlTimes));
}
for(;i>=0;--i){
m_data.set(i,0);
}
}


private void SHRIntegers(int nShrTimes) {
int nDataSize=m_data.size();
if(nShrTimes>=m_data.size()){
for(int i=0;i<nDataSize;++i){
m_data.set(i, 0);
}
return;
}
if(nShrTimes<0){
SHLIntegers(-nShrTimes);
return;
}
int i,finish=nDataSize-nShrTimes;
for(i=0;i<finish;++i){
m_data.set(i, m_data.get(i+nShrTimes));
}
for(;i<nDataSize;++i){
m_data.set(i,0);
}
}


private static int IntIndex(int index){
return index/Integer.SIZE;
}


private static int BitIndex(int index){
return index&(Integer.SIZE-1);
}


private static int AndBitInInt(int index){
return ~OrBitInInt(index);
}


private static int OrBitInInt(int index){
index=BitIndex(index);
return 1<<index;
}


/**
* 对int进行逻辑左移位
* @param i 原数
* @param nShlTimes 移位数,负数变右移
* @return 移位后的结果
*/
public static int SHLInteger(int i,int nShlTimes){
if(nShlTimes==0)return i;
if(nShlTimes>=Integer.SIZE)return 0;
if(nShlTimes<0)return SHRInteger(i, -nShlTimes);

int n=i<<nShlTimes;

return n;
}


/**
* 对int进行逻辑右移位
* @param i 原数
* @param nShrTimes 移位数,负数变左移
* @return 移位后的结果
*/
public static int SHRInteger(int i,int nShrTimes){
if(nShrTimes==0)return i;
if(nShrTimes>=Integer.SIZE)return 0;
if(nShrTimes<0)return SHLInteger(i, -nShrTimes);

int n=i>>nShrTimes;
int cover=Integer.MAX_VALUE>>(nShrTimes-1);
n&=cover;

return n;
}


}

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:5312次
    • 积分:135
    • 等级:
    • 排名:千里之外
    • 原创:8篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类