当简单的计算赶上了大数,其实大数运算也很简单

1、说三道四算法

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

可是,今天我想说的是,当咱们的运算遇到了大数,用本来的int、long、float、double数值类型工具

都没法表示出来的时候,大家想过该若是解决这一类型的问题了吗?优化

  在这,大家能够先不用看卤煮撸的代码,想一想若是本身遇到这个问题,该若是解决,也许你的想法spa

很新颖,思路以及在算法的实现上更清晰。但愿可以在广大的博友的集思广益下,大数的运算可以有code

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

 

2、大数运算之加法运算ci

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"));
    }
}
大数相加

 思路分析:rem

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

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

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

 

3、大数运算之减法运算

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"));
    }
}
大数相减

  思路分析:

  大数相减在实现上和大数相加殊途同归,也是经过循环遍历大数的每一位,对其进行数值相减,在遇到须要借位的数值,

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

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

 

4、大数运算之乘法运算

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"));
    }
}
大数相乘

 思路分析:

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

乘法的最终思路就是多个数值的加法运算。因此大数的乘法就是多个大数的加法运算。可是遇到两个数值都是大数的状况下,

运行速度会很是的慢。

 

5、大数运算之除法运算

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"));
    }
}
大数相除

  思路分析:

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

可是存在的问题仍是和大数的乘法是同样的,有待优化。

 

6、大数运算之工具类

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;
    }
    
}
工具类

  

7、卤煮有话说

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

优化和改善咱们的代码。你们有什么想法均可以说出来,咱们一块儿来探讨大数的加减乘除,让这么有意义的事能够获得

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

  想是一回事,作又是另外一回事。让咱们脑洞大开,集思广益一块儿来探讨吧!!!

 

  若是你以为博文写的不错,就点下【推荐一下】或【打赏卤煮一杯奶茶吧!!!

相关文章
相关标签/搜索