做高精度算法的人可能会遇到一个问题,就是如何表达0.1这个数字。如果把十进制的0.1转换成二进制,就会变成无限的小数。常规的做法是采用十进制高精度算法。但是十进制高精度算法的效率低,浪费内存。而且学过汇编和C语言的人一般会对这种方法感到很难以接受。那么我今天介绍的方法将成为你们更好的选择。

其实要解决这个问题,只要明白一个道理,计算机永远不可能保存绝对精确的数字。总有一部分小数要被截断。那么我们找到被保留的最低位,乘以十的n次方,就可以把这个小数变成整数了。换句话讲,所谓的小数,不过是一个小数点加上一个整数。

设以10000/10000 E0表示1,则1000/10000 E0就代表0.1了。0.1 ×0.1=(1000/10000 E0)×(1000/10000 E0)=(1000000 E(0+0)/10000)/10000=100 E0/10000=0.01。将0.01乘以10,把数量级减1就变成了0.1 E-1。

其实Java的BigInteger就是用二进制存储的,性能比我这个代码更好,建议大家还是使用Java自带的BigInteger。我是最近通过反射查看了BigInteger的私有变量"mag"后发现这个声明为int[] mag的数组就是BigInteger的内部实现方式。难怪BigInteger会有如此高的性能。而BigDecimal内部是用BigInteger实现的,所以也是二进制存储。原理应该与我的代码一致,但是优化更好。 一些Java视频教程中所说的BigInteger和BigDecimal是十进制存储的说法不对。我觉得实际项目中大家还是不要尝试自己设计高精度算法了,毕竟原理上最快速的算法已经由BigInteger实现并充分优化了。

二进制算法只有一个缺点,就是转换为十进制的时候会比较慢。如果是做大规模的高精度十进制仪表程序,倒是可以尝试一下十进制高精度算法。

下面提供JAVA算法实现:

//================实数======================

package psn.razerpen.math;

import java.io.Serializable;

public class SuperFloat_2 implements Comparable<SuperFloat_2>,Serializable{

/**

*/
private static final long serialVersionUID = 1L;

private static final String EXP_STRING=" e";

private SuperUINT m_value;
private SuperUINT m_one;
private int m_nDecPrecision;
private int m_nExp;
private boolean m_bNeg;

public SuperFloat_2() {
SetOneUINT(8);
m_value=new SuperUINT();
m_nExp=0;
m_bNeg=false;
}

public SuperFloat_2(SuperFloat_2 f) {
SetValue(f);
}

@Override
protected Object clone() throws CloneNotSupportedException {
return new SuperFloat_2(this);
}

public int GetDECPrecision(){
// System.out.println("N"+m_nDecPrecision);
// System.out.println("S"+(m_one.toString().length()-1));
return m_nDecPrecision;
}

public SuperFloat_2 SetDECPrecision(int p){
int nLastPrecision=GetDECPrecision();
int nSubPrecision=p-nLastPrecision;

if(nSubPrecision==0)return this;

if(nSubPrecision>0)SHL(nSubPrecision);
else SHR(-nSubPrecision);

SetOneUINT(p);

return this;
}

public SuperUINT GetValue(){
return m_value;
}

public SuperFloat_2 SetValue(String value, int exp){
SetDECPrecision(value.length());
m_value.SetValue(value);
SetExp(exp);
return Trim();
}

public SuperFloat_2 SetValue(SuperFloat_2 f) {
m_value=new SuperUINT(f.GetValue());
SetOneUINT(f.GetDECPrecision());
m_nExp=f.m_nExp;
m_bNeg=f.m_bNeg;
return this;
}

public int GetExp(){
return m_nExp;
}

private SuperFloat_2 SetExp(int exp){
m_nExp=exp;
return this;
}

public boolean GetNeg(){
return m_bNeg;
}

public SuperFloat_2 SetNeg(boolean bNeg){
m_bNeg=bNeg;
return this;
}

public SuperFloat_2 Trim(){
if(m_value.IsZero()){
m_nExp=0;
m_bNeg=false;
return this;
}

String strVal=m_value.toString();
String strPre=m_one.toString();
int nVal=strVal.length();
int nPre=strPre.length();

int nShr_t=nVal-nPre+1;
int nShl_t=nPre-nVal-1;

if(nShr_t>0){
SHR(nShr_t);
m_nExp+=nShr_t;
}else if(nShl_t>0){
SHL(nShl_t);
m_nExp-=nShl_t;
}

// int nSh_t=0;
// if(m_value.compareTo(m_one)>=0){
//
// nSh_t+=1;
// }
// if(nSh_t!=0){
// SHR(nSh_t);
// m_nExp+=nSh_t;
// return this;
// }
//
// SuperUINT m_one_t=new SuperUINT(m_one);
// m_one_t.DIV(SuperUINT.CONST_SUPERINTEGER_10);
// while(m_value.compareTo(m_one_t)<0){
// nSh_t+=1;
// }
// SHL(nSh_t);
// m_nExp-=nSh_t;
return this;
}

public SuperFloat_2 add(SuperFloat_2 a){return ADD(a);}

public SuperFloat_2 ADD(SuperFloat_2 a){
if(m_bNeg==a.m_bNeg)return _ADD(a);
else return _SUB(a);
}

public SuperFloat_2 sub(SuperFloat_2 a){return SUB(a);}

public SuperFloat_2 SUB(SuperFloat_2 a){
if(m_bNeg==a.m_bNeg)return _SUB(a);
else return _ADD(a);
}

public SuperFloat_2 mul(SuperFloat_2 a){return MUL(a);}

public SuperFloat_2 MUL(SuperFloat_2 a){
m_bNeg=m_bNeg!=a.m_bNeg;
//放大精度
int nLastPrec=m_value.GetPrecision();
m_value.SetPrecision(nLastPrec<<1);
//计算
SuperFloat_2 t=NewTempFloat(a);
m_value.MUL(t.m_value);
m_nExp+=t.m_nExp;
//缩小精度
Trim();
m_nExp-=GetDECPrecision();
return this;
}

public SuperFloat_2 div(SuperFloat_2 a){return DIV(a);}

public SuperFloat_2 DIV(SuperFloat_2 a){
if(a.IsZero()){
System.out.println("计算错误:除数为0");
return this;
}
if(IsZero()){
return this;
}
if(a==this){
m_value.CopyValue(SuperUINT.CONST_SUPERINTEGER_1,false);
Trim();
m_nExp=1;
m_bNeg=false;
return this;
}
m_bNeg=m_bNeg!=a.m_bNeg;
//放大精度
int nLastPrec=GetDECPrecision();
SetDECPrecision(nLastPrec<<1);
//计算
SuperFloat_2 t=NewTempFloat(a,nLastPrec);
m_value.DIV(t.m_value);
m_nExp-=t.m_nExp;
//缩小精度
Trim();
m_nExp+=nLastPrec;
SetDECPrecision(nLastPrec);
return this;
}

public boolean IsZero(){
return m_value.IsZero();
}

@Override
public boolean equals(Object obj) {
if(obj==null)return false;
if(obj==this)return true;
if(obj instanceof SuperFloat_2)return 0==compareTo((SuperFloat_2)obj);
else return false;
}

@Override
public int compareTo(SuperFloat_2 o) {
if(o==null)return m_bNeg?-1:1;
if(m_value.IsZero()){
if(o.IsZero()){
return 0;
}else if(o.m_bNeg){
return 1;
}else{
return -1;
}
}else if(m_bNeg){
if(o.IsZero()){
return -1;
}else if(o.m_bNeg){
return compareTo_Complex(o);
}else{
return -1;
}
}else{
if(o.IsZero()){
return 1;
}else if(o.m_bNeg){
return 1;
}else{
return compareTo_Complex(o);
}
}
}

@Override
public String toString() {
StringBuffer out=new StringBuffer(m_one.toString());
out.deleteCharAt(0);

String s=m_value.toString();

out.replace(out.length()-s.length(), out.length(), s);

out.insert(0, "0.");
if(m_bNeg) if(!m_value.IsZero()) out.insert(0, '-');
out.append(EXP_STRING);
out.append(m_nExp);

return out.toString();
}

public String toSicString(){
StringBuffer sb=new StringBuffer(toString());
int nFirstNum=0;
if(sb.charAt(0)=='-')nFirstNum=1;
sb.delete(nFirstNum, nFirstNum+2);
sb.insert(nFirstNum+1, '.');
int nExpPos=sb.indexOf(EXP_STRING);
sb.delete(nExpPos+EXP_STRING.length(), sb.length());
int nExpNum=GetExp()-1;
if(nExpNum>=0)sb.append('+');
sb.append(nExpNum);
return sb.toString();
}

public String toNumString(){
StringBuffer sb=new StringBuffer(toString());
if(sb.charAt(0)=='-')sb.deleteCharAt(0);
sb.delete(sb.indexOf(EXP_STRING), sb.length());

int nExp=GetExp();

if(nExp>0){
sb.deleteCharAt(0);
do{
int nDotPos=sb.indexOf(".");
sb.setCharAt(nDotPos, sb.charAt(nDotPos+1));
sb.setCharAt(nDotPos+1, '.');
if(nDotPos+1==sb.length()-1){
sb.append('0');
}
nExp-=1;
}while(nExp>0);
}else if(nExp<0){
do{
int nDotPos=sb.indexOf(".");
sb.setCharAt(nDotPos, sb.charAt(nDotPos-1));
sb.setCharAt(nDotPos-1, '.');
if(nDotPos-1==0){
sb.insert(0, '0');
}
nExp+=1;
}while(nExp<0);
}

if(m_bNeg)sb.insert(0, '-');

return sb.toString();
}

private SuperFloat_2 _ADD(SuperFloat_2 a){
SuperFloat_2 t=NewTempFloat(a);
SetEquExp(t);
m_value.SetPrecision(m_value.GetPrecision()+1).ADD(t.m_value).Trim();
return Trim();
}

private SuperFloat_2 _SUB(SuperFloat_2 a){
SuperFloat_2 t=NewTempFloat(a);
SetEquExp(t);
if(m_value.compareTo(t.m_value)>=0){
m_value.SetPrecision(m_value.GetPrecision()+1).SUB(t.m_value).Trim();
}else{
t.m_value.SetPrecision(t.m_value.GetPrecision()+1).SUB(m_value).Trim();
m_value=t.m_value;
m_bNeg=!m_bNeg;
}
return Trim();
}

private void SetOneUINT(int i) {
m_one=NewShBuffer(i);
m_nDecPrecision=i;
}

private int compareTo_Complex(SuperFloat_2 o) {
SuperFloat_2 t=NewTempFloat(this);
return t.SUB(o).m_bNeg?-1:1;
}

private void SetEquExp(SuperFloat_2 t) {
int subExp=t.m_nExp-m_nExp;
if(subExp>0){
SHR(subExp);
m_nExp+=subExp;
}else if(subExp<0){
subExp=-subExp;
t.SHR(subExp);
t.m_nExp+=subExp;
}
}

private void SHL(int nS){
SuperUINT a=NewShBuffer(nS);
m_value.SetPrecision(m_value.GetPrecision()+(nS+8)/9).MUL(a).Trim();
}

private void SHR(int nS) {
SuperUINT a=NewShBuffer(nS);
m_value.DIV(a).Trim();
}

private SuperUINT NewShBuffer(int nS){
StringBuffer sb=new StringBuffer("1");
for(int i=0;i<nS;++i){
sb.append(0);
}
return new SuperUINT(sb.toString());
}

private SuperFloat_2 NewTempFloat(SuperFloat_2 a) {
return NewTempFloat(a, this.GetDECPrecision());
}

private static SuperFloat_2 NewTempFloat(SuperFloat_2 a,int precision) {
return new SuperFloat_2(a).SetDECPrecision(precision);
}

}

//=========================整数=======================

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 SuperUINT implements Comparable<SuperUINT> , Serializable {

/**

*/
private static final long serialVersionUID = 3L;

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

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

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

}

/**

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

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

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

@Override
protected Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return new SuperUINT(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 SuperUINT 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;
}

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

/**
* 设置自然数值,低位在低索引,高低在高索引
* @param value
* @return
*/
public SuperUINT 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 SuperUINT 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 SuperUINT 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);
SuperUINT level=new SuperUINT(CONST_SUPERINTEGER_1).SetPrecision(GetPrecision());
SuperUINT num=new SuperUINT().SetPrecision(GetPrecision());

for(int i=0;i<value.length();++i){
SuperUINT num_t=new SuperUINT(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 SuperUINT 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 SuperUINT 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 SuperUINT CopyValue(SuperUINT 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;
}

/**
* 去除高位的 0 int值,节省存储空间
* @return this
*/
public SuperUINT 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 su(仅最低的一个int有效)
* @return
*/
public SuperUINT shl(SuperUINT su){return SHL(su);}

/**
* 逻辑左移位
* @param su(仅最低的一个int有效)
* @return
*/
public SuperUINT SHL(SuperUINT su) {
return SHL(su.GetInt(0));
}

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

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

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

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

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

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

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

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

/**
* 位与
* @param su
* @return
*/
public SuperUINT and(SuperUINT su){return AND(su);}

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

/**
* 位或
* @param su
* @return
*/
public SuperUINT or(SuperUINT su){return OR(su);}

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

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

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

/**
* 位同或
* @param su
* @return
*/
public SuperUINTwor(SuperUINT su){return WOR(su);}

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

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

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

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

/**
* 加法,高位截断
* @param a
* @return
*/
public SuperUINT ADD(SuperUINT 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 SuperUINT sub(SuperUINT a){return SUB(a);}

/**
* 减法
* @param a
* @return
*/
public SuperUINT SUB(SuperUINT a){
SuperUINT t=NewTempUINT(a);
ADD(t.NEG());
return this;
}

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

/**
* 乘法,高位截断
* @param a
* @return
*/
public SuperUINT MUL(SuperUINT a){
SuperUINT t=NewTempUINT(a);
SuperUINT ans=new SuperUINT().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 SuperUINT div(SuperUINT a){return DIV(a);}

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

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

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

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

SuperUINT t1=NewTempUINT(a,precision);
SuperUINT t2=NewTempUINT(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);
SuperUINT t_ans=new SuperUINT(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==this)return true;
if(obj instanceof SuperUINT)return 0==compareTo((SuperUINT)obj);
else return false;
}

/**
* this更大,或者o为空返回正
* 数值上一样大(精度可能不一样),返回0
* this更小,返回负
*/
@Override
public int compareTo(SuperUINT o) {
if(o==null)return 1;
if(this==o)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>();
SuperUINT su=new SuperUINT(this);
SuperUINT mod=new SuperUINT(new int []{0});
while(!su.IsZero()){
DivAndMod(su, mod, su, 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 static final StringBuffer STRING_BUFFER_INT_000=new StringBuffer();
static{
for(int j=0;j<Integer.SIZE;++j){
STRING_BUFFER_INT_000.append('0');
}
}
public String toBinaryString(String separator){
StringBuffer sb=new StringBuffer();
for(int i=m_data.size();i-->0;){
StringBuffer sb1=new StringBuffer(STRING_BUFFER_INT_000);
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 SuperUINT NewTempUINT(SuperUINT a){
return NewTempUINT(a, GetPrecision());
}

private static SuperUINT NewTempUINT(SuperUINT a,int precision) {
SuperUINT t=new SuperUINT(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;
}

}

十进制有限小数如何以二进制保存而不会变成无限小数相关推荐

  1. 当小数遇上二进制——全面解析JS中的小数二进制计算(附赠0.1+0.2 !== 0.3问题解释)

    二进制小数如何转换为十进制 二进制转换十进制的方法是: 从二进制数的最低位开始,每一位乘以对应的2的幂数,然后将最终的结果小数部分与整数部分分别相加 对应的2的幂,以个位为0,向高位依次增1,向地位依 ...

  2. 十进制进制法_关于二进制、十进制、八进制、十六进制数据转换计算方法详细总结...

    下面在安静的音乐中,让我们开始学习吧 公式库网 03:40来自生活用电 在我们接触编程知识时,总会接触有关进制转换的知识,最常见的就是10进制与二进制或十六进制之间的转换,很多时候我们总会遗忘,虽然现 ...

  3. 进制转换【最全进制转换汇总】(整数_小数_正数_负数)正负数整数小数十进制转任意进制-正负数整数小数任意进制转十进制-正负数低进制转高进制-正负数高进制转低进制

    文章目录: 补充知识点:各进制符号表示及其关系--二进制(B).八进制(O).十进制(D).十六进制(前缀OX,后缀H) 扩展:在线进制转换 第一部分:正数 一:[整数]正数十进制转任意进制:辗转相除 ...

  4. 为什么二进制保存的文件,打开仍然可以正常显示

    先看案例: 案例一. 结果输出: 案例二. 使用二进制读取文件,读取出来是二进制,正常显示需要转换:使用utf-8是不能成功的:因为当时字符串编写成二进制没有使用utf-8所以无法显示: 案例三. 可 ...

  5. 输入一个十进制数,转化为二进制

    1.代码如下: // test.cpp : Defines the entry point for the console application. // /* 输入一个十进制数,转化为二进制.*/ ...

  6. c语言二进制转化为十进制_将十进制转换为C中的二进制

    c语言二进制转化为十进制 Here you will get program to convert decimal to binary in C. 在这里,您将获得将C中的十进制转换为二进制的程序. ...

  7. 非负的十进制整数N转换为一个二进制

    题目 非负的十进制整数N转换为一个二进制 /****************************************************************************** ...

  8. python浮点数计算出现无限小数

    浮点数精度问题不是与编程语言种类关系不大,与进制转换有关 for i in range(20):print(0.1,'*',i, '=',0.1*i) 0.1 * 0 = 0.0 0.1 * 1 = ...

  9. 分数换算小数补0法_计算机存储整数和小数

    前言 有两个问题一直让我疑惑,第一个计算机存储整数为什么用反码来表示?第二个js中0.1+0.2为什么等于0.30000000000000004,计算机小数是如何存储的? 计算机的原码反码以及补码 对 ...

最新文章

  1. python selenium 进入新标签页_Python 爬虫 | 用selenium实现批改网的自动翻译
  2. MAP 最大后验——利用经验数据获得对未观测量的点态估计
  3. 转载--web前端工程化
  4. python 爬虫源代码-python 爬虫-1:下载网页源代码
  5. ajax发送异步请求四个步骤,深入理解ajax异步请求的五个步骤(详细代码)
  6. PIL Image resize 调整大小谜之操作
  7. EntityFramework进阶(三)- 根据IQueryable获取DbContext
  8. *【SGU - 114】Telecasting station (带权中位数 或 三分)
  9. Java 算法 特殊的数字四十
  10. VS2008编辑器代码适合的配色方案下载
  11. 深入了解VPP关键技术有哪些?
  12. Hive group by后面不能用列别名
  13. 学习Linux的七点忠告
  14. 用垃圾建设台湾海峡陆桥的主意是否可行
  15. 如何改变报表在页面显示的大小和位置?
  16. 高中计算机考试解析,2019下半年教师资格面试考试高中信息技术试题分析
  17. 期权波动率套利策略之谜
  18. Symantec Endpoint Protection 14.3 RU3 (macOS, Linux, Windows) - 端点安全解决方案
  19. 微信小程序 云开发 欢迎登录注册
  20. 最近邻搜索|Nearest neighbor search

热门文章

  1. SDL-软件安全设计初探
  2. Leetcode题库-回旋镖的数量(java语言版)
  3. 清华大学python吴萍答案_第732章 清华大学计算机系的扛把子
  4. 录屏工具有哪些?分享:电脑录制微课的工具和方法
  5. 联想笔记本怎么开启vt模式?
  6. JIRA安装部署详细文档
  7. python是一种面向____的高级语言_Python简介_语法_高薪Ptython系列专栏_2
  8. 卷积神经网络——24位彩色图像的卷积的详细介绍
  9. 表索引的定义、创建和使用
  10. 运动放大、视频放大、Video Motion Magnification、Video Magnification