博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
当简单的计算遇上了大数,其实大数运算也很简单
阅读量:5263 次
发布时间:2019-06-14

本文共 8908 字,大约阅读时间需要 29 分钟。

一、说三道四

   用代码实现简单的加减乘除运算会不会?只要你是个coder,我想这个答案都是肯定的吧!

但是,今天我想说的是,当我们的运算遇到了大数,用原本的int、long、float、double数值类型

都无法表示出来的时候,你们想过该如果解决这一类型的问题了吗?

  在这,你们可以先不用看卤煮撸的代码,想想如果自己遇到这个问题,该如果解决,也许你的想法

很新颖,思路以及在算法的实现上更清晰。希望能够在广大的博友的集思广益下,大数的运算能够有

一套更好的解决方案。不说了,咱们先撸代码吧。毕竟这才是主题!!!

 

二、大数运算之加法运算

package com.linjm.work;public class Add {    public String forAdd(String p, String q) {        String x = p;        String y = q;                int len = 0;        String res = "";                len = (x.length() > y.length()) ? x.length() : y.length();                        if (len == x.length())    y = Tools.fillZero(y, x.length() - y.length());        if (len == y.length())    x = Tools.fillZero(x, y.length() - x.length());                x = Tools.reverse(x);        y = Tools.reverse(y);                //m,n用于循环遍历时截取字符串x,y的每一位        //flag用于标识m和n的每一次相加是否需要进位        int m, n, flag = 0;                //遍历x、y,对应位相加        for (int i = 0; i < len; i++) {            int sum;                        m = Integer.parseInt(x.substring(i, i + 1));            n = Integer.parseInt(y.substring(i, i + 1));            sum = m + n;                        if (flag == 1) {                    sum = sum + 1;                flag = 0;            }                        if (sum >= 10) {                flag = 1;                sum = sum - 10;            }                        res += sum;        }                if (flag == 1)    //最高位相加后还大于10,则须进位            res += "1";                return Tools.reverse(res);    }                public static void main(String[] args) {        Add add = new Add();        System.out.println(add.forAdd("555555555555555555", "5555555555555555551"));    }}
大数相加

 思路分析:

  大数的相加主要是通过字符串的相加来实现的。两个大数相加,找出位数较大的那个大数获取对应的长度,

然后对较小的那个数进行左补0直至长度和较大的那个数的位数一样,最后循环累加两个大数的每一位的数值,

遇到需要进位的需要设一个标识位标识。

 

三、大数运算之减法运算

package com.linjm.work;public class Sub {        public String forSub(String p, String q) {        String x = p;        String y = q;                int len = 0;        String res = "";                int sign = 0;    //0: x >= y、1: x < y         sign = Tools.forMax(x, y) ? 0 : 1;                if (sign == 1) {            x = q;            y = p;        }                len = x.length();                y = Tools.fillZero(y, x.length() - y.length());                int m, n, flag = 0, num = 0;    //num标识出现0的次数,防止结果中高位出现多个0的情况                for (int i = len; i > 0; i--) {            int dif;                        m = Integer.parseInt(x.substring(i - 1, i));            n = Integer.parseInt(y.substring(i - 1, i));                        dif = m - n;                        //标志位如果等于1,说明存在借位            if (flag == 1) {                dif = dif - 1;                flag = 0;    //重置标志位            }                        //判断是否需要借位            if (dif < 0) {                flag = 1;    //标记                dif = dif + 10;            }                        if (dif == 0) {                num ++;            } else {                num = 0;            }                        res += dif;        }                if (Tools.isZero(res))            return "0";        if (num > 0) {            res = res.substring(0, res.length() - num);    //截取掉高位出现的连续num个0        }                return (sign == 1) ? "-" + Tools.reverse(res) : Tools.reverse(res);    }                public static void main(String[] args) {        Sub sub = new Sub();        System.out.println(sub.forSub("100000000", "1"));    }}
大数相减

  思路分析:

  大数相减在实现上和大数相加异曲同工,也是通过循环遍历大数的每一位,对其进行数值相减,在遇到需要借位的数值,

设立一个标识位进行标识。当遇到被减数比减数小的时候,先用减数减去被减数,用标识位标识被减数比减数小,最后结果

根据标识变量判断是否需要在结果上加上"-"。

 

四、大数运算之乘法运算

package com.linjm.work;public class Mul {    public String forMul(String p, String q) {        String x = Tools.maxNum(p, q);        String y = Tools.minNum(p, q);                if (y.length() > 15) {            return "ERROR:两位数中必须有一个数的长度要小于15";        }                    String sum = "0";                Add add = new Add();        Sub sub = new Sub();                while (Long.parseLong(y) > 0) {            sum = add.forAdd(sum, x);            y = sub.forSub(y, "1");        }                return sum;    }                public static void main(String[] args) {        Mul mul = new Mul();        System.out.println(mul.forMul("1000", "20000"));    }}
大数相乘

 思路分析:

   大数相乘在算法的实现上个人表示有点不太满意,虽然实现了功能,但还是觉得代码的实现上和思路都很挫。

乘法的最终思路就是多个数值的加法运算。所以大数的乘法就是多个大数的加法运算。但是遇到两个数值都是大数的情况下,

运行速度会非常的慢。

 

五、大数运算之除法运算

package com.linjm.work;public class Div {    public String forDiv (String p, String q) {        String x = p;        String y = q;                String res = "0";        String remain = "0";    //余数                if (!Tools.forMax(x, y)) {            return x + "的值要大等于" + y;         }                Add add = new Add();        Sub sub = new Sub();                while (true) {            x = sub.forSub(x, y);            res = add.forAdd(res, "1");                        if (!Tools.forMax(x, y)) {                remain = x;                break;            }        }                if (!Tools.isZero(remain))            res = res + "……" +remain;                return res;    }                public static void main(String[] args) {        Div div = new Div();        System.out.println(div.forDiv("222222222222222222222", "222222222222222222221"));    }}
大数相除

  思路分析:

  除法运算的实质也就是减法,让被除数一直减去除数,直到减不动了为止,统计下减了多少次除数,这个值就是商咯。

但是存在的问题还是和大数的乘法是一样的,有待优化。

 

六、大数运算之工具类

package com.linjm.work;public class Tools {    /**     * @param s num     * @Desc 字符串左补num个0     * @return String     * */    public static String fillZero(String s, int num) {        String res = "";                for (int i = 0; i < num; i++) {            res += "0";        }                return res + s;    }        /**     * @param s     * @Desc 反转字符串     * @return String     * */    public static String reverse(String s) {        String res = "";                for (int i = s.length(); i > 0 ; i--) {            res +=  s.substring(i - 1, i);        }                return res;    }        /**     * @param x n(n最小值为1)     * @Desc 获取字符串的n个字符     * @return int     * */    public static int numAt(String x, int n) {        return Integer.parseInt(x.substring(n - 1, n));    }            /**     * @param x y     * @Desc 获取两个大数中较大的数     *     注:此方法不对两个数是否是数字进行校验     * @return String     * */    public static String maxNum(String x, String y) {        String max = "";                if (x.length() > y.length()) {            max = x;        } else if (x.length() == y.length()) {            for (int i = 1; i <= x.length(); i++) {                if (numAt(x, i) != numAt(y, i)) {                    max = (numAt(x, i) > numAt(y, i)) ? x : y;                } else if (i == x.length()) {                    max = x;                }            }        } else if (x.length() < y.length()) {            max = y;        } else {            return "ERROR";        }        return max;    }            /**     * @param x y     * @Desc 获取两个大数中较小的数     *     注:此方法不对两个数是否是数字进行校验     * @return String     * */    public static String minNum(String x, String y) {        String min = "";                if (x.length() > y.length()) {            min = y;        } else if (x.length() == y.length()) {            for (int i = 1; i <= x.length(); i++) {                if (numAt(x, i) != numAt(y, i)) {                    min = (numAt(x, i) > numAt(y, i)) ? y : x;                } else if (i == x.length()) {                    min = x;                }            }        } else if (x.length() < y.length()) {            min = x;        } else {            return "ERROR";        }        return min;    }            /**     * @param x y     * @Desc 大数x是否大于大数y     * @return true/false     * */    public static boolean forMax(String x, String y) {        if (x.length() > y.length()) {            return true;        } else if (x.length() == y.length()) {            for (int i = 1; i <= x.length(); i++) {                if (numAt(x, i) != numAt(y, i)) {                    return (numAt(x, i) > numAt(y, i)) ? true : false;                } else if (i == x.length()) {                    return true;                }            }        } else if (x.length() < y.length()) {            return false;        } else {            System.out.println("ERROR!!!");        }        return false;    }                /**     * @param x     * @Desc 判断x是否是0或000……     * @return true/false     * */    public static boolean isZero(String x) {        boolean flag = true;                for (int i = 1; i <= x.length(); i++) {            if (Tools.numAt(x, i) != 0) {                return false;            }        }                return flag;    }    }
工具类

  

七、卤煮有话说

   也许撸主的代码算法的实现上可能会多多少少存在点瑕疵,第一遍写出来的代码不是最好的,但我们要尽我们所能去

优化和改善我们的代码。大家有什么想法都可以说出来,我们一起来探讨大数的加减乘除,让这么有意义的事可以得到

最优质的解决方案。在求知的路上,我们不怕批评,不怕失败,更不要在意别人的嘲笑,一步一步攀岩,我们终将登顶。

  想是一回事,做又是另一回事。让我们脑洞大开,集思广益一起来探讨吧!!!

 

  如果你觉得博文写的不错,就点下【推荐一下】或【打赏卤煮一杯奶茶吧!!!

转载于:https://www.cnblogs.com/JimLy-BUG/p/5965487.html

你可能感兴趣的文章
css & input type & search icon
查看>>
源代码的下载和编译读后感
查看>>
Kafka学习笔记
查看>>
Octotree Chrome安装与使用方法
查看>>
Windows 环境下基于 Redis 的 Celery 任务调度模块的实现
查看>>
趣谈Java变量的可见性问题
查看>>
C# 强制关闭当前程序进程(完全Kill掉不留痕迹)
查看>>
ssm框架之将数据库的数据导入导出为excel文件
查看>>
语音识别中的MFCC的提取原理和MATLAB实现
查看>>
验证组件FluentValidation的使用示例
查看>>
0320-学习进度条
查看>>
解决windows系统的oracle数据库不能启动ora-00119和ora-00130的问题
查看>>
ip相关问题解答
查看>>
MetaWeblog API Test
查看>>
反弹SHELL
查看>>
关闭Chrome浏览器的自动更新和升级提示
查看>>
移动、尺寸改变
查看>>
poj2255Tree Recovery【二叉树重构】
查看>>
tcpcopy 流量复制工具
查看>>
vue和react的区别
查看>>