java大数算法完成五则运算之除及取余

这几天偷懒去了~~今天把大数系列的最后一篇文章更新了~~


因为商和余其实是一个运算,只不过分属两个部分,所以放一起说了。


老样子,先来讲思路,原谅我水平有限,想不出来更好的方法,(有的话可以在下方评论告诉我~~)也没遇见过类似的可以借鉴的算法,于是就用我们平时做除法的方法。


如上图例子所示,商和余都是未知的,而且都是需要多次在尾部添加数据,那么数组弃用,集合又太庞大,但是我想到了用StringBuilder,数据可变,又方便添加数据,性能好,关键是还小,可以很方便的使用。


然后,我们需要一个循环来控制开始和结束,这个循环肯定是以被除数的最高位到最低位,那么我们用a代表被除数,b代表除数,就有了这个for (int i = 0; i < a.length; i++)循环,每次循环我们要将对应的被除数位a[i]添加至余数的末尾,然后将比较余数与除数,这时我们会得到三个结果之中的一个。

  • 余数小于除数:往商数的末尾加零,然后continue至下一次循环
  • 余数等于除数:往商数的末尾加一,清零余数,然后continue至下一次循环
  • 余数大于除数:这也是我们着重要考虑的分支。

由于循环是一位一位往前推进的,所以余数最多大除数一位,而一位的差距是不可能达到十倍的,最多商9。

例如除数101,被除数1000,余数为同样位数时为100,小于除数,进入下一循环,余数为1000,如果商10,除数与商的乘积 为1010,大于1000,所以只能商9,余89。

既然商只可能为1至9,那我完全可以用一个1至9的循环来找出商。

最后把添加商,同时用余数减去商与除数的乘积的差来当作新余数,进入下一循环。

取余也很简单,最后留下的余数即为余数。


最后上源代码:代码中所有调用到的函数请参考java大数算法完成五则运算之类基础


public BigNum div(BigNum div) throws Exception {
        int newNum[] = null;//商数组
        char newNumSign = 0;//商正负号
        if (SIGN == div.SIGN) {//同号为正,异号为负
            newNumSign = '+';
        } else {
            newNumSign = '-';
        }
        if (DIGITS < div.DIGITS) {//被除数位数小于除数,结果直接为零
            newNum = new int[1];
            newNum[0] = 0;
            newNumSign = '+';
        } else if (DIGITS == div.DIGITS) {//被除数位数等于除数
            switch (ArrCompare(NUM, div.NUM)) {//同位数下比较被除数与除数大小
                case -1://被除数小于除数
                    newNum = new int[1];
                    newNum[0] = 0;
                    newNumSign = '+';
                    break;
                case 0://被除数等于除数
                    newNum = new int[1];
                    newNum[0] = 1;
                    break;
                case 1://被除数大于除数
                    newNum = divAndRem(NUM, div.NUM, true);
                    break;
            }
        } else {//被除数位数大于除数
            newNum = divAndRem(NUM, div.NUM, true);
        }
        BigNum b = new BigNum(newNum, newNumSign);
        return b;
    }

    /**
     * 大数数组相除,a为被除数,b为除数,flag值为true返回商数,false返回余数     *
     * @param a
     * @param b
     * @param flag
     * @return
     */
    private int[] divAndRem(int a[], int b[], boolean flag) {
        StringBuilder quotient = new StringBuilder();//保存商数
        StringBuilder remainder = new StringBuilder();//保存余数
        //根据平常进行除法运算的方法来实现
        for (int i = 0; i < a.length; i++) {//被除数从最高位到最低位循环
            remainder.append(a[i]);//添加余数
            if ((i + 1) < b.length) {//如果余数位数小于除数,则给对应商数位赋零,同时进入下一层循环
                quotient.append(0);
                continue;
            }
            //当余数与除数位数一致或大于时判断余数与除数的大小
            switch (intArrCompaerTo(stringToIntArr(remainder.toString()), b)) {
                case -1://余数小于除数,给对应商数位赋零,同时进入下一层循环
                    quotient.append(0);
                    continue;
                case 0://余数等于除数,给对应商数位赋一,同时把余数清零
                    quotient.append(1);
                    remainder.delete(0, remainder.length());
                    break;
                case 1://余数大于除数
                    int remTemp[] = stringToIntArr(remainder.toString());//保存余数的数组
                    int jTemp[] = new int[1];//把j转换成数组以便运算
                    int proTemp[] = null;//保存j与b的乘积
                    for (int j = 1; j < 10; j++) {//最多只能为9
                        jTemp[0] = j;
                        proTemp = mulNum(jTemp, b);
                        int c = intArrCompaerTo(proTemp, remTemp);//保存除数乘商的积与余数的大小比的值
                        if (c == -1 && j != 9) {//积大于余数才继续,并且在商为9时即使积小于余数也要往下执行
                            continue;
                        }
                        if ((c == -1 && j == 9) || c == 0) {
                            //当商为9,积小于余数时,或者积等于余数时,不用将乘积的循环往前跳一次
                        } else {//将乘积的循环往前跳一次
                            jTemp[0] = --j;
                            proTemp = mulNum(jTemp, b);
                        }
                        quotient.append(j);//添加商
                        remainder.delete(0, remainder.length());//清空余数
                        remainder.append(intArrToString(subNum(remTemp, proTemp)));//添加余数减去积的差
                        break;
                    }
                    break;
            }
        }
        return flag ? stringToIntArr(quotient.toString()) : stringToIntArr(remainder.toString());
    }

    public BigNum rem(BigNum rem) throws Exception {
        int newNum[] = null;
        switch (compareTo(rem)) {//比较被除数与除数大小
            case -1://被除数小于除数时余数就是被除数本身
                return this;
            case 0://被除数等于除数时余数为零
                newNum = new int[1];
                newNum[0] = 0;
                break;
            case 1://被除数大于除数
                newNum = divAndRem(NUM, rem.NUM, false);
                break;
        }
        return new BigNum(newNum, '+');
    }


java大数算法完成五则运算这系列文章到这里也就结束了,有什么想法或建议欢迎在下方评论区告诉我,最后,写文不易~~点个赞吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值