C++高精度除以高精度

高精度除以高精度的问题,‌在计算机科学中是一个常见的挑战,‌特别是在处理非常大的数字时,‌这些数字超出了标准数据类型(‌如int或long long)‌的范围。‌这里,‌我们将详细解释一种常见的方法来解决这个问题:‌模拟手工除法。‌

基本思路

模拟手工除法的过程,‌即将一个高精度数(‌被除数)‌除以另一个高精度数(‌除数)‌,‌并逐位计算商和余数。‌

步骤详解

  1. 初始化:‌

    • 设定被除数 A 和除数 B(‌均为高精度数,‌通常以字符串或数组形式存储)‌。‌
    • 初始化商 Q为空字符串(‌或数组)‌,‌用于存储结果。‌
    • 初始化余数 R 为0(‌或与被除数相同长度的0字符串/数组)‌。‌
  2. 逐位处理:‌

    • 从被除数的最高位开始,‌每次处理一位(‌或几位,‌取决于除数的位数和精度要求)‌。‌
    • 将当前余数 R 乘以10(‌或相应的基数,‌如果是其他进制)‌,‌然后加上当前处理的被除数的那一位(‌或几位)‌。‌
    • 使用这个新的余数 R去除以除数 B,‌得到商 q 和新的余数 R。‌
    • 将 q 添加到商 Q 的末尾。‌
  3. 处理完所有位:‌

    • 当被除数的所有位都被处理完后,‌如果余数 R 不为0,‌则根据需要在商 Q 的末尾添加小数部分(‌如果需要计算小数除法)‌。‌
  4. 输出结果:‌

    • 将商 Q 转换为所需的输出格式(‌如字符串或数字)‌。‌

示例

假设我们要计算 12345÷123:

  • 初始化:‌Q="", R=0
  • 处理第一位(‌实际上,‌由于除数有三位,‌我们可能需要从“123”开始,‌但这里为了简化,‌我们从“1”开始并假设有前导0)‌:‌
    • R=0×10+1=1(‌小于除数,‌继续)‌
    • R=1×10+2=12(‌小于除数,‌继续)‌
    • R=12×10+3=123,‌123÷123=1,R=0
    • 将 1 添加到 Q,‌现在 Q="1"
  • 处理下一位(‌即“45”)‌:‌
    • R=0×10+45=45(‌小于除数,‌但这里我们直接处理整个“45”因为除数有三位)‌
    • 45÷123(‌实际上这里需要模拟长除法,‌但简化起见,‌我们知道它小于1,‌所以商为0,‌余数仍为45)‌
    • 注意:‌这里实际上需要更复杂的逻辑来准确处理,‌因为“45”不足以被“123”整除,‌我们需要继续从被除数中取更多的位。‌
  • (‌继续处理,‌直到所有位都被处理或达到所需精度)‌

注意:‌上面的示例简化了处理过程,‌实际实现中需要更复杂的逻辑来准确处理每一位,‌特别是当余数不足以直接除以除数时。‌

编程实现

编程实现时,‌可以使用数组或字符串来存储大数,‌并逐位(‌或逐段)‌进行除法操作。‌这通常涉及到大量的字符串操作或数组操作,‌以及模拟长除法的逻辑。‌由于篇幅限制,‌这里不给出具体的代码实现,‌但上述步骤应该为理解和实现高精度除法提供了足够的指导。‌

代码如下

#include <iostream>
#include <string>
using namespace std;
bool judge(int* a,int* b,int len){ //判断len长度的 b 是否可以被 a 除  
    if(a[len]>0) return true; //如果 a 比 b 长, 一定可以除 
    for(int i=len-1;i>=0;i--){//从 a 的最高位开始比 
        if(a[i]>b[i]) return true;//除去相等位的最高位大于b,说明a比b大,可以除 
        else if(a[i]<b[i]) return false;//除去相等位的最高位小于b,说明a比b小,不可以除 
    }
    return true;//a和b完全一样,可以除 
}
int main(){
    string a_s,b_s;
    int a[10001]={0},b[10001]={0},ans[521]={0};
    int i,j,len_a,len_b,len;
    cin>>a_s>>b_s;
    
    if(b_s=="0"){//除数不能为0 
        cout<<"除数不能为0"<<endl;
        return 0; 
    }
    
    len_a=a_s.length();//计算 a和 b的长度 
    len_b=b_s.length();
    len=len_a-len_b; //结果最开始的下标 
    
    for(i=0;i<len_a;i++) a[i]=a_s[len_a-1-i]-'0';//字符型转int型 
    for(i=0;i<len_b;i++) b[i]=b_s[len_b-1-i]-'0';
    
    for(i=len_a-len_b;i>=0;i--){
        while(judge(a+i,b,len_b)){//当a可以被b减的时候一直进行,直到不能被减,即得到最终的商 
            ans[i]++; //记录a被b减的次数,即为除法的结果 
            for(j=0;j<=len_b-1;j++){//高精度减法的实现方法 
                if(a[i+j]<b[j]){
                    a[i+j+1]--;
                    a[i+j]+=10;
                }
                a[i+j]-=b[j];
            }
        }
    }
    
    while(a[len_a]==0&&len_a>0) len_a--;//去掉前缀无用的零 
    while(ans[len]==0&&len>0) len--;
    
    for(i=len;i>=0;i--) cout<<ans[i];//输出结果 
    if(len<0) cout<<"0";//当被除数短于除数时,len<0不进行上一条语句,单独输出一个零 
    /*if(len_a>1||a[0]>0){//a最后没有减完的部分成为余数,余数为0就不输出 
        cout<<"余";
        for(i=len_a;i>=0;i--) cout<<a[i];
    } */ 
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值