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

2 篇文章 0 订阅
#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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大数据地图可以用vue的地图组件和数据可视化库来实现。以下是一个简单的示例。 1. 安装vue和地图组件 ```bash npm install vue vue2-google-maps ``` 2. 在vue中引入地图组件和数据可视化库 ```html <template> <div> <GmapMap :center="center" :zoom="zoom"> <GmapMarker v-for="(marker, index) in markers" :key="index" :position="marker.position" /> </GmapMap> </div> </template> <script> import { gmapApi } from 'vue2-google-maps' import * as d3 from 'd3' export default { data() { return { center: { lat: 37.7749, lng: -122.4194 }, zoom: 12, markers: [] } }, mounted() { // 获取数据 d3.json('data.json').then(data => { this.markers = data.map(item => { return { position: { lat: item.latitude, lng: item.longitude } } }) }) }, components: { GmapMap: gmapApi().then(() => import('vue2-google-maps/dist/components/map')), GmapMarker: gmapApi().then(() => import('vue2-google-maps/dist/components/marker')) } } </script> ``` 3. 在数据可视化库中绘制图表 ```html <template> <div> <GmapMap :center="center" :zoom="zoom" ref="map"> <GmapMarker v-for="(marker, index) in markers" :key="index" :position="marker.position" /> </GmapMap> <div ref="chart"></div> </div> </template> <script> import { gmapApi } from 'vue2-google-maps' import * as d3 from 'd3' import * as d3GeoProjection from 'd3-geo-projection' export default { data() { return { center: { lat: 37.7749, lng: -122.4194 }, zoom: 12, markers: [] } }, mounted() { // 获取数据 d3.json('data.json').then(data => { this.markers = data.map(item => { return { position: { lat: item.latitude, lng: item.longitude } } }) // 绘制图表 const width = 600 const height = 400 const svg = d3.select(this.$refs.chart) .append('svg') .attr('width', width) .attr('height', height) const projection = d3GeoProjection.geoMercator() .center([-122.4194, 37.7749]) .translate([width / 2, height / 2]) .scale(400000) const path = d3.geoPath().projection(projection) svg.selectAll('path') .data(data) .enter() .append('path') .attr('fill', '#ccc') .attr('stroke', '#333') .attr('stroke-width', 1) .attr('d', path) }) }, components: { GmapMap: gmapApi().then(() => import('vue2-google-maps/dist/components/map')), GmapMarker: gmapApi().then(() => import('vue2-google-maps/dist/components/marker')) } } </script> ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值