Java写一个计算器类(NumberCalculator),能看懂的都是大神

一直想实现一个计算类,但是苦于没有好的思路,最近闲来无事,理清思路,不服就干,话不多说,直接上代码。
相信各位都是编程界大神,代码思想就不用说了,懂的都懂。

package com.bbm.normaltool.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Vector;
import java.util.function.BiFunction;

import lombok.Getter;

// 计算器:可以避免各个类型数字之间的运算之间的类型转换,并可以按照运算符优先级计算,如:
// 2*2 + 3*3 + 4*4 + 5*5 = 54
//
// @author BBM

public class NumberCalculator {
    private BigDecimal value = BigDecimal.ZERO;
    private final List<CalFactor> calFactors;

    public NumberCalculator(Number newValue) {
        this.calFactors = new Vector<>();
        this.add(newValue);
    }

    public static NumberCalculator zero() {
        return new NumberCalculator(0);
    }

    public static NumberCalculator one() {
        return new NumberCalculator(1);
    }

    // 多个数连加:A+B+C
    public NumberCalculator add(Number... numArray) {
        Objects.requireNonNull(numArray);
        BigDecimal temp = BigDecimal.ZERO;
        for (Number number : numArray) {
            temp = temp.add(new BigDecimal(number.toString()));
        }
        this.calFactors.add(new CalFactor(CalOperator.ADD, temp, null, null));
        return this;
    }

    public NumberCalculator add(NumberCalculator... calculatorArray) {
        Objects.requireNonNull(calculatorArray);
        BigDecimal temp = BigDecimal.ZERO;
        for (NumberCalculator calculator : calculatorArray) {
            temp = temp.add(calculator.get());
        }
        this.calFactors.add(new CalFactor(CalOperator.ADD, temp, null, null));
        return this;
    }

    // 多个数连减:-A-B-C
    public NumberCalculator sub(Number... numArray) {
        Objects.requireNonNull(numArray);
        BigDecimal temp = BigDecimal.ZERO;
        for (Number number : numArray) {
            temp = temp.add(new BigDecimal(number.toString()));
        }
        this.calFactors.add(new CalFactor(CalOperator.SUB, temp, null, null));
        return this;
    }

    public NumberCalculator sub(NumberCalculator... calculatorArray) {
        Objects.requireNonNull(calculatorArray);
        BigDecimal temp = BigDecimal.ZERO;
        for (NumberCalculator calculator : calculatorArray) {
            temp = temp.add(calculator.get());
        }
        this.calFactors.add(new CalFactor(CalOperator.SUB, temp, null, null));
        return this;
    }

    // 多个数连乘:A*B*C

    public NumberCalculator mul(Number... numArray) {
        Objects.requireNonNull(numArray);
        BigDecimal temp = BigDecimal.ONE;
        for (Number number : numArray) {
            temp = temp.multiply(new BigDecimal(number.toString()));
        }
        this.calFactors.add(new CalFactor(CalOperator.MUL, temp, null, null));
        return this;
    }

    public NumberCalculator mul(NumberCalculator... calculatorArray) {
        Objects.requireNonNull(calculatorArray);
        BigDecimal temp = BigDecimal.ONE;
        for (NumberCalculator calculator : calculatorArray) {
            temp = temp.multiply(calculator.get());
        }
        this.calFactors.add(new CalFactor(CalOperator.MUL, temp, null, null));
        return this;
    }

    public NumberCalculator div(Number num, int scale, RoundingMode roundMode) {
        Objects.requireNonNull(num);
        this.calFactors.add(new CalFactor(CalOperator.DIV, new BigDecimal(num.toString()), scale, roundMode));
        return this;
    }

    public NumberCalculator div(NumberCalculator otherCalculator, int scale, RoundingMode roundMode) {
        Objects.requireNonNull(otherCalculator);
        this.calFactors.add(new CalFactor(CalOperator.DIV, otherCalculator.get(), scale, roundMode));
        return this;
    }

    // 利用现有的value值和calFactors里面的数据进行计算,
    // 得出新的value值,并将calFactors清空,避免重复计算。
    public NumberCalculator cal() {
        if (!this.calFactors.isEmpty()) {
            BigDecimal newValue = this.value;

            if (this.calFactors.size() == 1) {
                newValue = this.calFactors.get(0).cal(newValue);
            } else {

                // 简化计算过程,将乘除运算改成简单加减运算:
                // 输入:2+2*3*4-5/8
                // tempOptFactors[0]=[+,0]
                // tempOptFactors[1]=[+,2]
                // tempOptFactors[1]=[+,2*3*4=24]
                // tempOptFactors[1]=[-,5/8=0.625]
                // 最终变成 ==》
                // tempOptFactors[0]=[+,0]
                // tempOptFactors[1]=[+,2]
                // tempOptFactors[1]=[+,24]
                // tempOptFactors[1]=[-,0.625]
                List<CalFactor> tempCalFactors = new ArrayList<>();
                tempCalFactors.add(new CalFactor(CalOperator.ADD, newValue, null, null));
                CalFactor tempCalFactor = null;
                BigDecimal tmp;
                for (int i = 1; i < this.calFactors.size(); i++) {
                    CalFactor calFactor = this.calFactors.get(i);
                    CalFactor lastCalFactor = this.calFactors.get(i - 1);
                    if (calFactor.getCalOperator() == CalOperator.ADD
                        || calFactor.getCalOperator() == CalOperator.SUB) {
                        if (tempCalFactor == null) {
                            tempCalFactors.add(lastCalFactor);
                        } else {
                            tempCalFactors.add(tempCalFactor);
                        }
                        if (i == this.calFactors.size() - 1) {
                            tempCalFactors.add(calFactor);
                        }
                        tempCalFactor = null;
                    } else {
                        if (tempCalFactor == null) {
                            tempCalFactor = lastCalFactor;
                        }
                        tmp = calFactor.cal(tempCalFactor.getNum());
                        tempCalFactor.setNum(tmp);
                    }
                }

                if (tempCalFactor != null) {
                    tempCalFactors.add(tempCalFactor);
                }

                newValue = BigDecimal.ZERO;
                for (CalFactor calFactor : tempCalFactors) {
                    newValue = calFactor.cal(newValue);
                }

            }
            this.calFactors.clear();
            this.value = newValue;
        }
        return this;
    }

    public NumberCalculator setScale(int scale, RoundingMode roundMode) {
        this.value = this.cal().value.setScale(scale, roundMode);
        return this;
    }

    public BigDecimal get() {
        return this.cal().value;
    }

    public BigDecimal get(int scale, RoundingMode roundMode) {
        return this.setScale(scale, roundMode).value;
    }

    public double getDoubleValue() {
        return this.get().doubleValue();
    }

    public long getLongValue() {
        return this.get().longValue();
    }

    public int getIntValue() {
        return this.get().intValue();
    }

    public float getFloatValue() {
        return this.get().floatValue();
    }

    public short getShortValue() {
        return this.get().shortValue();
    }

    public byte getByteValue() {
        return this.get().byteValue();
    }

    enum CalOperator {// 运算符
        ADD("+", (b, c) -> b.add(c.getNum())),
        SUB("-", (b, c) -> b.subtract(c.getNum())),
        MUL("*", (b, c) -> b.multiply(c.getNum())),
        DIV("/", (b, c) -> b.divide(c.getNum(), c.getScale(), c.getRoundMode()));

        private final String code;

        private final BiFunction<BigDecimal, CalFactor, BigDecimal> function;

        CalOperator(String newCode, BiFunction<BigDecimal, CalFactor, BigDecimal> newFunction) {
            this.code = newCode;
            this.function = newFunction;
        }

        BigDecimal cal(BigDecimal b, CalFactor c) {
            return this.function.apply(b, c);
        }
    }

    @Getter
    static final class CalFactor {// 每个计算元素/计算因子
        private final CalOperator calOperator;
        private BigDecimal num;
        private final Integer scale;// 仅除法时生效
        private final RoundingMode roundMode;// 仅除法时生效

        CalFactor(CalOperator newCalOperator, BigDecimal newNum, Integer newScale, RoundingMode newRoundMode) {
            this.calOperator = newCalOperator;
            this.num = newNum;
            this.scale = newScale;
            this.roundMode = newRoundMode;
        }

        public BigDecimal cal(BigDecimal b) {
            return this.calOperator.cal(b, this);
        }

        public void setNum(BigDecimal newNum) {
            this.num = newNum;
        }
    }
}

执行一把看看结果:

public static void main(String[] args) {

        // 2*2 + 3*3 + 4*4 + 5*5 = 54
        NumberCalculator cal = new NumberCalculator(0);
        for (int i = 2; i <= 5; i++) {
            cal.add(i).mul(i);
        }
        System.out.println(cal.get());

        // ((((2*2)+3)*3+4)*4+5)*5=525
        NumberCalculator cal2 = new NumberCalculator(0);
        for (int i = 2; i <= 5; i++) {
            cal2.add(i).cal().mul(i);
        }
        System.out.println(cal2.get());

        // (1+2)*(3+4)*(5+6)*(7+8)=3465
        NumberCalculator cal3 =
            new NumberCalculator(1).add(2)
                .cal()
                .mul(new NumberCalculator(3).add(4))
                .mul(new NumberCalculator(5).add(6))
                .mul(new NumberCalculator(7).add(8));
        System.out.println(cal3.get());

        // (4+4+4+4)*(5+5+5+5)*(6+6+6+6)=7680
        NumberCalculator cal4 =
            new NumberCalculator(0).add(4, 4, 4, 4)
                .cal()
                .mul(new NumberCalculator(0).add(5, 5, 5, 5))
                .mul(new NumberCalculator(0).add(6, 6, 6, 6));
        System.out.println(cal4.get());

        // (4+4+4+4)*(5+5+5+5)*(6+6+6+6)=7680
        NumberCalculator cal5 =
            new NumberCalculator(1).mul(
                new NumberCalculator(0).add(4, 4, 4, 4),
                new NumberCalculator(0).add(5, 5, 5, 5),
                new NumberCalculator(0).add(6, 6, 6, 6));
        System.out.println(cal5.get());

        // 1-2-3-4-5-6-7-8-9-10
        NumberCalculator cal6 = new NumberCalculator(1).sub(2, 3, 4, 5, 6, 7, 8, 9, 10);
        System.out.println(cal6.get());

        // ((1+2*3*4)/5+44)/7
        System.out.println(
            new NumberCalculator(1).add(2)
                .mul(3, 4)
                .cal()
                .div(5, 4, RoundingMode.HALF_UP)
                .add(44)
                .cal()
                .div(7, 4, RoundingMode.HALF_UP)
                .get());

    }

输出结果如下:
在这里插入图片描述
从代码执行结果上看,简直就是YYDS,而且只要是继承了Number类的数字类型,都可以直接传入,有效避免了做类型转换,输出结果支持7种数据类型,保证够你使。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值