自己编写的大数据精确计算类

it2022-05-05  156

#include "bigdecimal.h" #include<QDebug> BigDecimal::BigDecimal() { } BigDecimal::BigDecimal(QString decimal) { this->decimal=decimal; } QString BigDecimal::add(QString a, QString b) { //如果小数点在开头 if(a.startsWith("."))a="0"+a; if(b.startsWith("."))b="0"+b; if(a.startsWith("-."))a=a.replace(QRegExp("^-\\."),"-0."); if(b.startsWith("-."))b=b.replace(QRegExp("^-\\."),"-0."); if(!isNum(a)||!isNum(b))return "NaN";   //如果小数点在结尾 a=a.replace(QRegExp("[.]$"),""); b=b.replace(QRegExp("[.]$"),""); //判断a,b是否为负数 bool aIsFushu=a.startsWith("-"); bool bIsFushu=b.startsWith("-"); //去掉负号 if(aIsFushu)a=a.mid(1); if(bIsFushu)b=b.mid(1);   if(!aIsFushu&&bIsFushu){//a正b负 return subtract(a,b); }else if(aIsFushu&&!bIsFushu){//a负b正 return subtract(b,a); }else if(aIsFushu&&bIsFushu){//a负b负 return "-"+add(a,b); }   //a正b正 //a小数长度 int dotA=a.contains(".")?a.length()-1-a.lastIndexOf("."):0; //b小数长度 int dotB=b.contains(".")?b.length()-1-b.lastIndexOf("."):0; //最终小数位 int dot=dotA>=dotB?dotA:dotB; //去小点变整数 int posA=a.lastIndexOf("."),posB=b.lastIndexOf("."); if(posA>0)a=a.remove(posA,1); if(posB>0)b=b.remove(posB,1); //结尾补0使小数位对齐 QString endZeroA,endZeroB; endZeroA=endZeroA.fill('0',dot-dotA); endZeroB=endZeroB.fill('0',dot-dotB); a=a+endZeroA; b=b+endZeroB;   //前补0使字符串等长   int lenA=a.length();//防止输入00000这类的串导致的位数错误 int lenB=b.length(); int len=lenA>=lenB?lenA:lenB; QString preZeroA,preZeroB; preZeroA=preZeroA.fill('0',len-lenA); preZeroB=preZeroB.fill('0',len-lenB); a=preZeroA+a; b=preZeroB+b;   QString result=""; int jing=0; for (int i =len-1; i>=0; i--) { bool ok1,ok2; int aa=a.mid(i,1).toInt(&ok1,10);//转换失败返回0 int bb=b.mid(i,1).toInt(&ok2,10); if(!(ok1&&ok2))return "NaN"; int res=aa+bb+jing;//对位相加的结果 int remain=res>=10?res-10:res; if(i==0)remain=res; jing=res>=10?1:0; result=QString("%1").arg(remain)+result; } if(dot!=0){ result=result.insert(result.length()-dot,"."); } //去掉前置的0 QRegExp reg("^0+"); result=result.replace(reg,""); if(result.isEmpty())result="0"; if(result.startsWith("."))result="0"+result;//纠正.25类型的偏差 return result; }   QString BigDecimal::subtract(QString a, QString b) { //如果小数点在开头 if(a.startsWith("."))a="0"+a; if(b.startsWith("."))b="0"+b; if(a.startsWith("-."))a=a.replace(QRegExp("^-\\."),"-0."); if(b.startsWith("-."))b=b.replace(QRegExp("^-\\."),"-0.");   if(!isNum(a)||!isNum(b))return "NaN"; //如果小数点在结尾 a=a.replace(QRegExp("[.]$"),""); b=b.replace(QRegExp("[.]$"),""); //判断a,b是否为负数 bool aIsFushu=a.startsWith("-"); bool bIsFushu=b.startsWith("-"); //去掉负号 if(aIsFushu)a=a.mid(1); if(bIsFushu)b=b.mid(1);   if(!aIsFushu&&bIsFushu){//a正b负 return add(a,b); }else if(aIsFushu&&!bIsFushu){//a负b正 return "-"+add(a,b); }else if(aIsFushu&&bIsFushu){//a负b负 return subtract(b,a); }   //a正b正 //a小数长度 int dotA=a.contains(".")?a.length()-1-a.lastIndexOf("."):0; //b小数长度 int dotB=b.contains(".")?b.length()-1-b.lastIndexOf("."):0; //最终小数位 int dot=dotA>=dotB?dotA:dotB; //去小点变整数 int posA=a.lastIndexOf("."),posB=b.lastIndexOf("."); if(posA>0)a=a.remove(posA,1); if(posB>0)b=b.remove(posB,1); //结尾补0使小数位对齐 QString endZeroA,endZeroB; endZeroA=endZeroA.fill('0',dot-dotA); endZeroB=endZeroB.fill('0',dot-dotB); a=a+endZeroA; b=b+endZeroB;   //前补0使字符串等长 //防止输入00000这类的串导致的位数错误 int lenA=a.length(); int lenB=b.length(); int len=lenA>=lenB?lenA:lenB; QString preZeroA,preZeroB; preZeroA=preZeroA.fill('0',len-lenA); preZeroB=preZeroB.fill('0',len-lenB); a=preZeroA+a; b=preZeroB+b;   QString result=""; int jie=0;//借位 bool isFushu=false;//是否是负数 for (int i =len-1; i>=0; i--) { bool ok1,ok2; int aa=a.mid(i,1).toInt(&ok1,10);//转换失败返回0 int bb=b.mid(i,1).toInt(&ok2,10); if(!(ok1&&ok2))return "NaN"; int res=aa-bb-jie;//对位相减的结果,jie之前被借回的数 int remain=res<0?res+10:res; jie=res<0?1:0; if(i==0&&jie==1)//最高位需借时,即为负数 { isFushu=true; result=""; jie=0; break; } result=QString("%1").arg(remain)+result; } if(isFushu){ for (int i =len-1; i>=0; i--) { bool ok1,ok2; int aa=a.mid(i,1).toInt(&ok1,10);//转换失败返回0 int bb=b.mid(i,1).toInt(&ok2,10); if(!(ok1&&ok2))return "NaN"; int res=bb-aa-jie;//对位相加的结果 int remain=res<0?res+10:res; jie=res<0?1:0; result=QString("%1").arg(remain)+result; } } if(dot!=0){ result=result.insert(result.length()-dot,"."); } //去掉前置的0 QRegExp reg("^0+"); result=result.replace(reg,""); if(result.isEmpty())result="0"; if(result.startsWith("."))result="0"+result; result=isFushu?"-"+result:result;//是负数加负号 return result; }   QString BigDecimal::multiply(QString a, QString b) { //如果小数点在开头 if(a.startsWith("."))a="0"+a; if(b.startsWith("."))b="0"+b; if(a.startsWith("-."))a=a.replace(QRegExp("^-\\."),"-0."); if(b.startsWith("-."))b=b.replace(QRegExp("^-\\."),"-0.");   if(!isNum(a)||!isNum(b))return "NaN"; //如果小数点在结尾 a=a.replace(QRegExp("[.]$"),""); b=b.replace(QRegExp("[.]$"),""); QString result="0"; //确定计算结果的正负 bool isFuA=a.startsWith("-"); bool isFuB=b.startsWith("-"); bool isFuRes=false; if(!isFuA&&!isFuB)isFuRes=false;//a正b正 if(!isFuA&&isFuB)isFuRes=true;//a正b负 if(isFuA&&!isFuB)isFuRes=true;//a负b正 if(isFuA&&isFuB)isFuRes=false;//a负b负 //去掉负号 if(isFuA)a=a.mid(1); if(isFuB)b=b.mid(1); //确定结果的小数位数 int decLenA=a.contains(".")?a.length()-1-a.lastIndexOf("."):0; int decLenB=b.contains(".")?b.length()-1-b.lastIndexOf("."):0; int decLenRes=decLenA+decLenB; //去掉小数点 int posA=a.lastIndexOf("."),posB=b.lastIndexOf("."); if(posA>0)a=a.remove(posA,1); if(posB>0)b=b.remove(posB,1);   //b的长度 int lenB=b.length(); for (int i =lenB-1; i>=0; i--) { QString strB=b.mid(i,1); QString res=moreXsingle(a,strB); if(res=="NaN")return res; //每次计算要补的0 QString zero=QString("0").repeated((lenB-1-i)); res=res+zero; result=add(result,res); } //加小数点 if(decLenRes>0){ QString zero1="0"; //对于结果不足小数位时前补0 result=zero1.repeated(decLenRes-result.length()+1)+result; result=result.insert(result.length()-decLenRes,"."); //两者取小数多者 int lenMax=decLenA>decLenB?decLenA:decLenB; //截掉结尾的0数 int num1=decLenRes-lenMax; result=result.replace(QRegExp(QString("0{%1}$").arg(num1)),"");//去掉结尾的0 } if(result.endsWith("."))result=result.left(result.length()-1); //加负号 if(isFuRes)result="-"+result; return result; }   QString BigDecimal::divide(QString a, QString b, int decimalLen) { //如果小数点在开头 if(a.startsWith("."))a="0"+a; if(b.startsWith("."))b="0"+b; if(a.startsWith("-."))a=a.replace(QRegExp("^-\\."),"-0."); if(b.startsWith("-."))b=b.replace(QRegExp("^-\\."),"-0.");   if(!isNum(a)||!isNum(b))return "NaN"; //如果小数点在结尾 a=a.replace(QRegExp("[.]$"),""); b=b.replace(QRegExp("[.]$"),""); //判断b是否为0 QString tempb=b; QString tmp=b.replace(QRegExp("^-"),"").replace(".","") .replace(QRegExp("^0"),""); if(tmp.isEmpty())return "NaN"; b=tempb;   QString result="0"; //确定计算结果的正负 bool isFuA=a.startsWith("-"); bool isFuB=b.startsWith("-"); bool isFuRes=false; if(!isFuA&&!isFuB)isFuRes=false;//a正b正 if(!isFuA&&isFuB)isFuRes=true;//a正b负 if(isFuA&&!isFuB)isFuRes=true;//a负b正 if(isFuA&&isFuB)isFuRes=false;//a负b负 //去掉负号 a=a.replace(QRegExp("^-"),""); b=b.replace(QRegExp("^-"),""); //获取小数位数 int decLenA=a.contains(".")?a.length()-1-a.lastIndexOf("."):0; int decLenB=b.contains(".")?b.length()-1-b.lastIndexOf("."):0; int decMax=decLenA>=decLenB?decLenA:decLenB;//取小数位数大者 //分子分母同乘倍数,转换为整数 QString beishu="1"+QString("0").repeated(decMax);   a=multiply(a,beishu); b=multiply(b,beishu);   //如果小数点后有虚0,则删除之,以便使用整数乘法 a=a.replace(QRegExp("\\.0+$"),""); b=b.replace(QRegExp("\\.0+$"),"");   int lenA=a.length(); //初始化被除数 QString aa=""; QString cha=""; //是否整除 bool zhengChu=false;   for (int i =0; i < lenA+decimalLen+1; ++i) { if(i<lenA)aa=cha+a.mid(i,1); else aa=cha+"0"; //试商 zhengChu=false;//是否整除 for (int j = 9; j>=0; j--) { QString res=QString("%1").arg(j); QString ji=multiply(res,b); cha=subtract(aa,ji); if(cha.startsWith("-")){ cha=""; continue; }else{//试商成功 if(i==lenA){ result+="."; } result+=res; //当有小数时才去判断是否整除,不出小数只是补0,无需跳出 if(i>=lenA){ //差和余数中不全为0时即为整除,需跳出不再往下计算 if((cha+a.mid(i+1)).indexOf(QRegExp("[1-9]+"))==-1){ zhengChu=true; break; }else{ zhengChu=false; } } break; } } if(zhengChu)break; } result=result.replace(QRegExp("^0+"),""); if(result.isEmpty())result="0";//纠正上一步全为0替换成""的偏差 if(result.startsWith("."))result="0"+result;//纠正.25之类的偏差 if(isFuRes)result="-"+result; if(!zhengChu)//如果除不尽,则按定位四余五入 result=BigDecimal(result).round(decimalLen).toString(); else{//如果整除,删除小数点后末尾的0或.00等 result=result.replace(QRegExp(".0+$|0+$"),""); } return result; }   BigDecimal BigDecimal::round(int len) { if(!isNum(decimal))return BigDecimal("NaN"); //数字的总长(含小数点) int decLen=decimal.length(); //是否是小数 bool isDecimal=decimal.contains("."); //是否是负数 bool isFu=decimal.startsWith("-"); //小数点的位置 int dotIndex=isDecimal?decimal.lastIndexOf("."):decLen-1; //小数位长度 int dotLen=decLen-1-dotIndex; //整数位长度 int intLen=isDecimal?dotIndex:decLen; //---开始判断是否是数字--- QString newDecimal=decimal; //去掉小数点 if(decimal.contains("."))newDecimal=newDecimal.remove(dotIndex,1); //去掉负号 newDecimal=newDecimal.replace(QRegExp("^-"),""); for (int i = 0; i < newDecimal.length(); ++i) { bool ok; newDecimal.mid(i,1).toInt(&ok,10); if(!ok)return BigDecimal("0"); } //---结束判断是否是数字---   QString result=""; QString zero=""; if(len<=0){ if(isFu)intLen=intLen-1; newDecimal=newDecimal.mid(0,intLen); if(intLen<-len)return BigDecimal("0"); int numAfterLen=newDecimal.mid(intLen+len,1).toInt();   if(numAfterLen>=5) result=add(newDecimal.left(intLen+len)+QString("0").repeated(-len),"1"+QString("0").repeated(-len)); else result=newDecimal.left(intLen+len)+QString("0").repeated(-len); result=result.replace(QRegExp("^0+"),""); if(result.isEmpty())return BigDecimal("0"); if(isFu)result="-"+result;   }else{ if(!isDecimal){//如果是整数 zero=zero.fill('0',len); result=decimal+"."+zero; }else if(dotLen<=len){//如果小数位少于len zero=zero.fill('0',len-dotLen); result=decimal+zero; }else{//如果小数位多于len int numAfterLen=decimal.mid(dotIndex+len+1,1).toInt(); if(numAfterLen>=5){ result=isFu?add(decimal.mid(0,dotIndex+len+1),"-0."+QString("0").repeated(len-1)+"1"): add(decimal.mid(0,dotIndex+len+1),"0."+QString("0").repeated(len-1)+"1"); }else{ result=decimal.mid(0,dotIndex+1+len); } } } return BigDecimal(result); }   BigDecimal BigDecimal::ceiling(int len) { if(!isNum(decimal))return BigDecimal("NaN"); if(len<0)return decimal; bool isFu=decimal.startsWith("-"); bool isDecimal=decimal.contains(".");   //转为正数 decimal=decimal.replace(QRegExp("^-"),"");   QString result=""; if(!isDecimal){ result=decimal; }else{ //获取小数位数 int intLen=decimal.lastIndexOf("."); int decLen=decimal.length()-1-intLen;   if(decLen<=len)result=decimal;//原数返回 else if(len>0&&!isFu)result= add(decimal.left(intLen+1+len),"0."+QString("0").repeated(len-1)+"1"); else if(len>0&&isFu)result= decimal.left(intLen+1+len); else if(!isFu) result=add(decimal.left(intLen),"1"); else if(isFu) result=decimal.left(intLen); } if(isFu)result="-"+result; return BigDecimal(result); }   BigDecimal BigDecimal::floor(int len) { if(!isNum(decimal))return BigDecimal("NaN"); if(len<0)return BigDecimal(decimal); bool isFu=decimal.startsWith("-"); bool isDecimal=decimal.contains(".");   //转为正数 decimal=decimal.replace(QRegExp("^-"),"");   QString result=""; if(!isDecimal){ result=decimal; }else{ //获取小数位数 int intLen=decimal.lastIndexOf("."); int decLen=decimal.length()-1-intLen;   if(decLen<=len)result=decimal;//原数返回 else if(len>0&&!isFu)result= decimal.left(intLen+1+len); else if(len>0&&isFu)result= add(decimal.left(intLen+1+len),"0."+QString("0").repeated(len-1)+"1"); else if(!isFu) result=decimal.left(intLen); else if(isFu) result=add(decimal.left(intLen),"1"); } if(isFu)result="-"+result; return BigDecimal(result); }   QString BigDecimal::toString() { return this->decimal; }   BigDecimal BigDecimal::operator+(const BigDecimal &bigDecimal) { QString result=add(this->decimal,bigDecimal.decimal); return BigDecimal(result); } BigDecimal BigDecimal::operator-(const BigDecimal &bigDecimal) { QString result=subtract(this->decimal,bigDecimal.decimal); return BigDecimal(result); }   BigDecimal BigDecimal::operator*(const BigDecimal &bigDecimal) { QString result=multiply(this->decimal,bigDecimal.decimal); return BigDecimal(result); }   BigDecimal BigDecimal::operator/(const BigDecimal &bigDecimal) {   QString a=this->decimal; QString b=bigDecimal.decimal; //获取小数位数,最大保留10位 QString result=divide(a,b,10); return BigDecimal(result); }   bool BigDecimal::operator>(const BigDecimal &bigDecimal) { if(compare(this->decimal,bigDecimal.decimal)==-2)return false; return compare(this->decimal,bigDecimal.decimal)==1; }   bool BigDecimal::operator==(const BigDecimal &bigDecimal) { if(compare(this->decimal,bigDecimal.decimal)==-2)return false; return compare(this->decimal,bigDecimal.decimal)==0; }   bool BigDecimal::operator>=(const BigDecimal &bigDecimal) { if(compare(this->decimal,bigDecimal.decimal)==-2)return false; return compare(this->decimal,bigDecimal.decimal)>=0; }   bool BigDecimal::operator<(const BigDecimal &bigDecimal) { if(compare(this->decimal,bigDecimal.decimal)==-2)return false; return compare(this->decimal,bigDecimal.decimal)==-1; }   bool BigDecimal::operator<=(const BigDecimal &bigDecimal) {   if(compare(this->decimal,bigDecimal.decimal)==-2)return false; return compare(this->decimal,bigDecimal.decimal)<=0; }   int BigDecimal::compare(QString a, QString b) { QString cha=subtract(a,b); if(cha=="NaN")return -2; if(cha.contains("-"))return -1; else if(cha=="0")return 0; else return 1; }   QString BigDecimal::moreXsingle(QString a, QString b) { if(a.isEmpty()||b.isEmpty())return "NaN"; QString result="0"; bool ok; int numB=b.toInt(&ok,10); if(!ok||b.contains("-"))return "NaN"; int len=a.length(); for (int i =len-1; i>=0;i--) { QString strA=a.mid(i,1); int numA=strA.toInt(&ok,10); if(!ok)return "NaN"; int res=numA*numB; //每次计算要补的0 QString zero=QString("0").repeated(len-1-i); QString resStr=QString("%1").arg(res)+zero; result=add(result,resStr); } return result; }   bool BigDecimal::isNum(QString decimal) { QRegExp reg("^-?[0-9]+[.]?[0-9]*$"); reg.setCaseSensitivity(Qt::CaseSensitive); if(reg.indexIn(decimal)==-1)return false; else return true; }

最新回复(0)