19.仿简道云公式函数实战-数学函数-CEILING

1. CEILING函数

CEILING 函数可以将参数 number 向上/向下舍入为最接近的指定基数的倍数。

2. 函数用法

CEILING(number, significance)

其中各参数的含义如下:

  • number: 必需。 要舍入的值。

  • significance: 必需。 要舍入到的倍数。

对于不同符号的参数搭配,具体计算规则如下:

  • 当 number 为正时,不管 significance 为正或为负,对值按远离 0 的方向进行向上舍入;

  • 当 number 为负,significance 为正时,对值按朝向 0 的方向进行向上舍入;

  • 当 number 和 significance 都为负时,对值按远离 0 的方向进行向下舍入。

3. 函数示例

公式 说明 结果
CEILING(10, 3) 将 10 向上舍入到最接近的 3 的倍数 12
CEILING(10, -3) 将 10 向上舍入到最接近的 -3 的倍数 12
CEILING(-10, 3) 将 -10 向上舍入到最接近的 3 的倍数 -9
CEILING(-10, -3) 将 -10 向下舍入到最接近的 -3 的倍数 -12

4. 代码实战

首先我们在function包下创建math包,在math包下创建CeilingFunction类,代码如下:

package com.ql.util.express.self.combat.function.math;

import com.ql.util.express.Operator;
import com.ql.util.express.self.combat.exception.FormulaException;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 类描述: CEILING函数
 *
 * @author admin
 * @version 1.0.0
 * @date 2023/11/23 9:31
 */
public class CeilingFunction extends Operator {

    public CeilingFunction(String name) {
        this.name = name;
    }

    @Override
    public Object executeInner(Object[] objects) throws Exception {

        // 参数校验
        if (objects.length != 2) {
            throw new FormulaException("操作数异常");
        }

        Object result = 0;
        // 考虑精度问题
        if (isPrecise) {
            BigDecimal number = new BigDecimal(objects[0].toString());
            BigDecimal multiple = new BigDecimal(objects[1].toString());
            result = precise(number,multiple);
        } else {
            // 根据objects数组中的第一个数,无论什么数据类型,一律按照double处理
            double n = Double.parseDouble(objects[0].toString());
            double s = Double.parseDouble(objects[1].toString());
            result = ceiling(n,s);
        }

        return result;
    }

    private static double ceiling(double n, double s) {
        if (n>0.0D && s<0.0D) {
            s = Math.abs(s);
        }
        return n > 0.0D && s < 0.0D?0.0D / 0.0:(n != 0.0D && s != 0.0D?Math.ceil(n / s) * s:0.0D);
    }

    private static BigDecimal precise(BigDecimal number, BigDecimal multiple) {
        BigDecimal zero = BigDecimal.ZERO;

        int comparisonResult = multiple.compareTo(zero);

        int flag = number.compareTo(zero);

        BigDecimal roundedNumber = BigDecimal.ZERO;
        if (flag >= 0 && comparisonResult >=0) {
            roundedNumber = number.divide(multiple, 0, RoundingMode.CEILING).multiply(multiple);
        } else if (flag < 0 && comparisonResult >=0) {
            roundedNumber = number.divide(multiple, 0,RoundingMode.CEILING).multiply(multiple);
        } else if (flag >= 0 && comparisonResult < 0) {
            roundedNumber = number.divide(multiple, 0,RoundingMode.FLOOR).multiply(multiple);
        }

        else if (flag < 0 && comparisonResult < 0) {
            roundedNumber = number.divide(multiple, 0).multiply(multiple);
        }

        return roundedNumber;
    }

}

把CeilingFunction类注册到公式函数入口类中,代码如下:

package com.ql.util.express.self.combat.ext;

import com.ql.util.express.ExpressRunner;
import com.ql.util.express.IExpressResourceLoader;
import com.ql.util.express.parse.NodeTypeManager;
import com.ql.util.express.self.combat.function.logic.*;
import com.ql.util.express.self.combat.function.math.AbsFunction;
import com.ql.util.express.self.combat.function.math.AvgFunction;
import com.ql.util.express.self.combat.function.math.CeilingFunction;

/**
 * 类描述: 仿简道云公式函数实战入口类
 *
 * @author admin
 * @version 1.0.0
 * @date 2023/11/21 15:29
 */
public class FormulaRunner extends ExpressRunner {

    public FormulaRunner() {
        super();
    }

    public FormulaRunner(boolean isPrecise, boolean isTrace) {
        super(isPrecise,isTrace);
    }

    public FormulaRunner(boolean isPrecise, boolean isStrace, NodeTypeManager nodeTypeManager) {
        super(isPrecise,isStrace,nodeTypeManager);
    }

    public FormulaRunner(boolean isPrecise, boolean isTrace, IExpressResourceLoader iExpressResourceLoader, NodeTypeManager nodeTypeManager) {
        super(isPrecise,isTrace,iExpressResourceLoader,nodeTypeManager);
    }

    @Override
    public void addSystemFunctions() {
        // ExpressRunner 的内部系统函数
        super.addSystemFunctions();
        // 扩展公式函数
        this.customFunction();
    }
    /***
     * 自定义公式函数
     */
    public void customFunction() {

        // 逻辑公式函数
        this.addLogicFunction();

        // 数学公式函数
        this.addMathFunction();
    }

    public void addLogicFunction() {
        // AND函数
        this.addFunction("AND",new AndFunction("AND"));

        // IF函数
        this.addFunction("IF",new IfFunction("IF"));

        // IFS函数
        this.addFunction("IFS",new IfsFunction("IFS"));

        // XOR函数
        this.addFunction("XOR",new XorFunction("XOR"));

        // TRUE函数
        this.addFunction("TRUE",new TrueFunction("TRUE"));

        // FALSE函数
        this.addFunction("FALSE",new FalseFunction("FALSE"));

        // NOT函数
        this.addFunction("NOT",new NotFunction("NOT"));

        // OR函数
        this.addFunction("OR",new OrFunction("OR"));
    }

    public void addMathFunction() {
        // ABS函数
        this.addFunction("ABS",new AbsFunction("ABS"));

        // AVERAGE函数
        this.addFunction("AVERAGE",new AvgFunction("AVERAGE"));

        // CEILING函数
        this.addFunction("CEILING",new CeilingFunction("CEILING"));
    }
}

创建测试用例

package com.ql.util.express.self.combat;

import com.ql.util.express.DefaultContext;
import com.ql.util.express.self.combat.ext.FormulaRunner;
import org.junit.Test;

/**
 * 类描述: 实战测试类
 *
 * @author admin
 * @version 1.0.0
 * @date 2023/11/21 15:45
 */
public class CombatTest {

    @Test
    public void CEILING() throws Exception{

        FormulaRunner formulaRunner = new FormulaRunner(true,true);
        // 创建上下文
        DefaultContext context = new DefaultContext<>();
        String express = "CEILING(a,b)";
//        context.put("a",10);
//        context.put("b",3);

//        System.out.println(12);

//        context.put("a",10);
//        context.put("b",-3);
//        System.out.println(12);
//        context.put("a",-10);
//        context.put("b",3);
//        System.out.println(-9);
//
        context.put("a",-10);
        context.put("b",-3);
        Object object = formulaRunner.execute(express, context, null, true, true);
        System.out.println(object);

    }

}

运行结果

19.仿简道云公式函数实战-数学函数-CEILING_第1张图片

你可能感兴趣的:(仿简道云公式函数实战,java,算法,数据结构)