大整数减法自己实现

java 中针对大整数的运算,提供了 BigInteger 和 BigDecimal ,那么我们 自己如何实现大整数的减法呢?

我们 回忆下 减法的竖式 ,在减法竖式中,我们先减 个位数,再减十位数,如果个位数不够减则像 十位借1,个

位数加上10,计算结果作为个位数结果,十位数字 减一。小数 减大数 = - ( 大数 - 小数):(ps:小数 减大数结果

就是 大数减小数 前面加一个负号)

换成更一般的说法:就是 计算第 i 位相减的时候 需要考虑到 第 i-1 位产生的借位。

类比到 计算机:我们使用char[]数组进行存储 加数和被加数,结果存储到StringBuild

因为我们输入的数是高位在左边,因此我们遍历的时候从最右边遍历,也就是代码中的

pos = len -1, 我们定义一个 变量表示 借位:jieWei,初始值为 0,后续我们计算 第 i 位的差

的时候就可以直接使用如下放方法:

公式:ch1 -'0':从字符 转换成对应的 数字 比如:‘3’-‘0’ = 3

第i位的差 就是:int sub= ch1 - ch2 - jin;

如果 sub < 0 ,则 我们 jieWei= 1, char sumChar = sub +10 +'0' ,

如果 sub >= 0  则 我们 jieWei= 0,

最后一步,千万别忘了,我们还有一个进位!!!

我们把进位 放在最高位。

(ps:StringBuild : 中 insert(i,k),就是在第i的位置插入,当i = 0,也就是说插入到最左边,就是插入到最高位)
我们不考虑 是负数的情况(减数 和被减数 都是正数,如果 有负数时情况会复杂,后续会分析)

 

   /**
     * 减法,不考虑负数相减
     * @param arr1
     * @param arr2
     * @return
     */
    private static StringBuilder getSubResult(char[] arr1, char[] arr2){
        int len1 = arr1.length;
        int len2 = arr2.length;
        char ch1,ch2;
        // 如果被减数的位数 ,少于减数 则结果为负,如果位数相同,逐位比较,直道比较出大小
        boolean positive = false;
        // 
        if(len1 > len2){
            positive = true;
        }
        if(len1 == len2){
        // 长度一样时候,逐位比较(可以考虑使用string.compareTo)
            int temp = 0;
            while (temp < len1){
                ch1 = arr1[temp];
                ch2 = arr2[temp];
                if(ch1 != ch2){
                    positive = (ch1> ch2);
                    break;
                }
                temp ++;

            }
        }
        if(positive){
          return bigSubSmall(arr1,arr2);
        }
        // 负数,前面添加负号
        return bigSubSmall(arr2,arr1).insert(0,"-");
    }

 

 

   /**
     * 大数减小数
     * @param bigArr 较大的数
     * @param smallArr 较小的数
     * @return
     */
    private static StringBuilder bigSubSmall(char[] bigArr, char[] smallArr){
        int len1 = bigArr.length;
        int len2 = smallArr.length;
        char[] resultArr = new char[len1];
        // 借位
        int jieWei = 0;
        int pos1 = len1-1,pos2 = len2 -1;
        char ch1,ch2;
        int resultBit = 0;
        int i = len1 -1;
        while (pos2>=0){
            // 被减数减去 被借去的 值,如果没有借位,jieWei =0,有借位 值 =1
            ch1 = (char)( bigArr[pos1--] - jieWei) ;
            ch2 = smallArr[pos2--];
            resultBit = ch1 - ch2;
            // 此处需注意:因为 i 传入函数,在函数中对i-- 出来函数i值是不变的
            jieWei = saveResultAndGetJieWei(resultBit,resultArr,i);
            i --;
        }
        while (pos1>=0){
            ch1 = bigArr[pos1--];
            resultBit =  ch1 - jieWei -'0';
            jieWei = saveResultAndGetJieWei(resultBit,resultArr,i);
            i --;
        }
        StringBuilder sb = new StringBuilder(len1);
        int j=0;
        //移除高位的0
        for (;j<len1;j++){
            if(resultArr[j]!='0'){
                break;
            }
        }
        for (;j<len1;j++){
            sb.append(resultArr[j]);
        }

        return sb;
    }
    private static  int saveResultAndGetJieWei(int resultBit,char[] resultArr,int index){
        int jieWei = 0;
        if(resultBit < 0){
            resultBit = resultBit +10 ;
            jieWei = 1;
        }
        // 此处 index 和 index --,出了函数 ,调用者的值是不变的
        resultArr[index] = (char) (resultBit+'0');
        return jieWei;
    }

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值