设计一个100亿的计算器

        在最近看到一个面试题,要求设计一个100亿的计算器。当时第一下想到的是考察各种数据类型的取值范围。基本的数据类型long是可以满足要求的。也就是说,可以使用long来进行 + - / 的计算,但是如果进行乘法的计算,那么可能会超出long的最大取值。

        那么就会用到java的面向对象的设计思想了。设计一个类可以表示一个很大的数。并且提供了与另外一个整数进行加减乘除的计算功能。


这是来自一个大神的代码

package pac02;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 100亿的计算器
 * @author acer
 *
 */
public class Calculate {
    private char sign = '0';   // 0 表示正数  - 表示负数
    private byte[] data;

    public Calculate() {
        this.data = "0".getBytes();
    }

    public Calculate(String value) throws Exception {
        //正则表达式,输入字符串要求以 零个或一个 - 开头,其余都是数字
        Pattern pattern = Pattern.compile("^-?\\d+$");

        if (value == null || value.length() <= 0) {
            value = "0";
        }
        Matcher matcher = pattern.matcher(value);
        if (!matcher.find()) {
            throw new Exception("the value is not a number string :" + value);
        }
        //获取字符串的第一个字符
        char firstChar = value.charAt(0);

        //data应该保存的是第一个非0数字后的字符串
        if (firstChar == '-') {  //说明输入的是个负数
            if (value.length() >=2) {
                sign = firstChar;
                value = value.substring(1);
                value = getTemp(value); //得到value中第一个非0后的子字符串。
            }
        } else {
            value = getTemp(value);
        }
        this.data = value.getBytes();
    }

    /**
     * 得到一个字符串第一个非0后的字符串,如果没有找到,则返回 "0" 。如:00003435534,则返回3435534
     * @return
     */
    private String getTemp(String value){
        Pattern pattern = Pattern.compile("[^0]{1}");
        Matcher matcher = pattern.matcher(value);
        if (matcher.find()) {
            value = value.substring(matcher.start());
        } else {
            value = "0";
        }
        return value;
    }

    public Calculate add(Calculate other) {
        Calculate result = new Calculate();
        int thisLength = this.data.length;
        int otherLength = other.data.length;
        int shorterLength = thisLength > otherLength ? otherLength : thisLength;
        ArrayList<Byte> resultData = new ArrayList<Byte>();
        int flag = 0;  //表示相加时的 进位,或相减时的 借位
        int i = thisLength - 1;
        int j = otherLength - 1;
        int k = shorterLength;

        //两个数的符号相同
        if (other.sign == this.sign) {
            //从两个整数的个位开始依次相加
            while (k > 0) {
                Integer temp = new Integer(new String(new byte[]{this.data[i]})) + new Integer(new String(new byte[]{other.data[j]})) + flag;
                flag = temp / 10;  //相加结果超过10时的进位。没有超过10,进位为 0
                resultData.add(0, ((temp % 10) + "").getBytes()[0]);  //把相加结果保存起来
                k--;
                i--;
                j--;
            }
            //把多出的位加入到结果中
            if (i == -1) {
                while (j >= 0) {
                    Integer temp = new Integer(new String(new byte[]{other.data[j]})) + flag;
                    flag = temp / 10;
                    resultData.add(0, ((temp % 10) + "").getBytes()[0]);
                    j--;
                }
            } else if (j == -1) {
                while (i >= 0) {
                    Integer temp = new Integer(new String(new byte[]{this.data[i]})) + flag;
                    flag = temp / 10;
                    resultData.add(0, ((temp % 10) + "").getBytes()[0]);
                    i--;
                }
            }
            //最后把flag加进结果中
            if (flag != 0) {
                for (byte by : (flag + "").getBytes()) {
                    resultData.add(0, by);
                }
            }
            result.sign = other.sign;
        } else {  //符号不同
            if (thisLength > otherLength) {  //说明this表示的整数绝对值大,所以最终结果的符号为this的符号
                result.sign = this.sign;
                resultData = subtract(this.data, other.data);  //执行减法
            } else if (thisLength < otherLength) {  //other表示的整数绝对值大,所以最终结果的符号为other的符号
                result.sign = other.sign;
                resultData = subtract(other.data, this.data);
            } else {  //如果两个数据的位数相同
                Integer thisInt = 0;
                Integer otherInt = 0;
                //从第一位开始比较,直到两者不相等
                for (int n = 0; n < thisLength; n++) {
                    thisInt = new Integer(new String(new byte[]{this.data[n]}));
                    otherInt = new Integer(new String(new byte[]{other.data[n]}));
                    if (!thisInt.equals(otherInt)) {   //注意这里要使用equals方法,因为这里需要比较的是两者的内容
                        break;
                    }
                }

                //如果this的绝对值大
                if (thisInt > otherInt) {
                    result.sign = this.sign;
                    resultData = subtract(this.data, other.data);
                } else {
                    result.sign = other.sign;
                    resultData = subtract(other.data, this.data);
                }
            }
        }
        result.data = new byte[resultData.size()];
        for (int m = 0; m < resultData.size(); m++) {
            result.data[m] = resultData.get(m);
        }
        return result;
    }

    private ArrayList<Byte> subtract(byte[] larger, byte[] smaller) {
        ArrayList<Byte> resultData = new ArrayList<Byte>();
        int flag = 0;
        int i = smaller.length - 1;
        int j = larger.length - 1;
        int k = smaller.length;
        while (k > 0) {
            Integer temp = new Integer(new String(new byte[]{larger[j]})) + flag - new Integer(new String(new byte[]{smaller[i]}));
            if (temp < 0) { //如果相减结果小于0,说明需要借位,则把flag置为 -1,以便下一位减去
                flag = -1;
                temp += 10;
            } else {       //如果大于零,需要把flag置为 0.不要忘记了
                flag = 0;
            }
            resultData.add(0, (temp + "").getBytes()[0]);
            j--;
            i--;
            k--;
        }
        //下面的代码就不写注释了
        while (j >= 0) {
            Integer temp = new Integer(new String(new byte[]{larger[j]})) + flag;
            if (temp < 0) {
                flag = -1;
                temp += 10;
            } else {
                flag = 0;
            }
            resultData.add(0, (temp + "").getBytes()[0]);
            j--;
        }
        return resultData;
    }


    @Override
    public String toString() {
        String str = new String(this.data);
        str = getTemp(str);
        if (sign == '-' && str !="0") {
            str = sign + str;
        }
        return str;
    }

}


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值