zoukankan      html  css  js  c++  java
  • JavaScript实现将存在变量的计算类型字符串转为计算式,并得到最终结果。

    今天拿到一个需求,需要将'20+15.3+{a}/{b}-2*3.0'后台传过来的字符串进行运算并拿到最终值,其中还可以传变量,也允许浮点数的存在,在参考了中国的流浪猫<js方------将字符串转换成算术表达式,并计算出结果,例如(‘92-4*5/3‘)>https://blog.csdn.net/weixin_46611729/article/details/121293766<js 实现String.format()>https://blog.csdn.net/a258831020/article/details/46988887之后实现了需求,其中主要增加的是对浮点数部分的处理,代码如下

    function accAdd(arg1, arg2) {
    var r1, r2, m;
    try {
    r1 = arg1.toString().split(".")[1].length;
    } catch (e) {
    r1 = 0
    }

    try {
    r2 = arg2.toString().split(".")[1].length;
    } catch (e) {
    r2 = 0
    }
    m = Math.pow(10, Math.max(r1, r2));
    return (arg1 * m + arg2 * m) / m;
    }
    Number.prototype.add = function(arg) {
    return accAdd(arg, this);
    }
    // 除法
    function accDiv(arg1, arg2) {
    var t1 = 0,
    t2 = 0,
    r1, r2;
    try {
    t1 = arg1.toString().split(".")[1].length;
    } catch (e) {
    r1 = 0
    }

    try {
    t2 = arg2.toString().split(".")[1].length;
    } catch (e) {
    r2 = 0
    }
    r1 = Number(arg1.toString().replace(".", ""));
    r2 = Number(arg2.toString().replace(".", ""));
    return (r1 / r2) * Math.pow(10, t2 - t1);
    }
    Number.prototype.div = function(arg) {
    return accDiv(this, arg);
    }
    // 乘法
    function accMul(arg1, arg2) {
    var m = 0,
    s1 = arg1.toString(),
    s2 = arg2.toString();
    try {
    m += s1.split(".")[1].length
    } catch (e) {
    }
    try {
    m += s2.split(".")[1].length
    } catch (e) {
    }
    return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)
    }
    Number.prototype.mul = function(arg) {
    return accMul(arg, this);
    }
    // 减法
    function acCut(arg1, arg2) {
    var r1, r2, m;
    try {
    r1 = arg1.toString().split('.')[1].length;
    } catch (e) {
    r1 = 0
    }
    try {
    r2 = arg2.toString().split('.')[1].length;
    } catch (e) {
    r2 = 0
    }
    m = Math.pow(10, Math.max(r1, r2));
    return (arg1 * m - arg2 * m) / m;
    }
    Number.prototype.cut = function(arg) {
    return acCut(this, arg);
    }

    String.prototype.format = function(args) {
    var result = this;
    if (arguments.length > 0) {
    if (arguments.length == 1 && typeof(args) == "object") {
    for (var key in args) {
    if (args[key] != undefined) {
    var reg = new RegExp("({" + key + "})", "g");
    result = result.replace(reg, args[key]);
    }
    }
    } else {
    for (var i = 0; i < arguments.length; i++) {
    if (arguments[i] != undefined) {
    //var reg = new RegExp("({[" + i + "]})", "g");//这个在索引大于9时会有问题
    var reg = new RegExp("({)" + i + "(})", "g");
    result = result.replace(reg, arguments[i]);
    }
    }
    }
    }
    return result;
    }
    const isNumber = (val) => {
    const regPos = /^\d+(\.\d+)?$/ // 非负浮点数
    const regNeg = /^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$/ // 负浮点数
    if (regPos.test(val) || regNeg.test(val)) {
    return true
    } else {
    return false
    }
    }

    function getDecimals(arr) {
    const index = arr.indexOf('.')
    // 找到第一个小数点
    // 找到之后拿出前面的
    if (index != -1) {
    let arr1 = arr.slice(0, index)
    let arr2 = arr.slice(index + 1)
    // 将前面那一部分倒叙,然后拿出截止到计算符号之前的东西
    arr1 = arr1.reverse()
    let number1 = []
    let number2 = []
    let len1 = 0
    let len2 = 0
    for (let item of arr1) {
    if (isNumber(item)) {
    number1.push(item)
    len1 += 1
    } else {
    break
    }
    }
    // 直接操作后面那一部分的
    for (let item of arr2) {
    if (isNumber(item)) {
    number2.push(item)
    len2 += 1
    } else {
    break
    }
    }
    number1 = number1.reverse()
    // 将number1中的元素和number中的元素以及小数点拼接起来就是那个小数
    let arr3 = [...number1, '.', ...number2]
    let number3 = ''
    arr3.map(item => {
    number3 = number3 + `${item}`
    })
    arr.splice(index - len1, index + len2 - 1, Number(number3))
    return getDecimals(arr)
    } else {
    return arr
    }
    }

    function sumResutl(arr) {
    // 如果数组元素中有乘除加减运算符
    const i1 = arr.indexOf('*')
    const i2 = arr.indexOf('/')
    const i3 = arr.indexOf('-')
    const i4 = arr.indexOf('+')
    if (i1 !== -1) {
    // 拿到*运算符前面数字的索引
    const index = i1 - 1
    // 计算出结果
    const result = arr[index].mul(arr[i1 + 1])
    // 修改数组元素
    arr.splice(index, 3, result)
    // 如果剩下的元素不只一位,则继续调用函数自身
    if (arr.length > 1) {
    sumResutl(arr)
    }
    } else if (i2 !== -1) {
    // 拿到/运算符前面数字的索引
    const index = i2 - 1
    // 计算出结果
    const result = arr[index].div(arr[i2 + 1])
    // 修改数组元素
    arr.splice(index, 3, result)
    // 如果剩下的元素不只一位,则继续调用函数自身
    if (arr.length > 1) {
    sumResutl(arr)
    }
    } else if (i3 !== -1) {
    // 拿到-运算符前面数字的索引
    const index = i3 - 1
    // 计算出结果
    const result = arr[index].cut(arr[i3 + 1])
    // 修改数组元素
    arr.splice(index, 3, result)
    // 如果剩下的元素不只一位,则继续调用函数自身
    if (arr.length > 1) {
    sumResutl(arr)
    }
    } else if (i4 !== -1) {
    // 拿到+运算符前面数字的索引
    const index = i4 - 1
    // 计算出结果
    const result = arr[index].add(arr[i4 + 1])
    // 修改数组元素
    arr.splice(index, 3, result)
    // 如果剩下的元素不只一位,则继续调用函数自身
    if (arr.length > 1) {
    sumResutl(arr)
    }
    }
    return arr[0]
    }
    export function compute(str, arges) {
    let data = str.format(arges)
    // 拿到结果之后开始处理为运算
    const arr = data.split('')
    // 准备一个容器
    let newArray = []
    // 遍历字符串数组
    arr.forEach((item, i) => {
    // 如果当前字符串是数字
    if (isNumber(item)) {
    // 拿到最后一个数组元素
    let endStr = newArray[newArray.length - 1]
    // 拿到最后一个数组元素的索引
    const endIndex = newArray.length - 1
    // 判断最后一个数组元素是否是数字
    if (isNumber(endStr)) {
    // 如果最后一个数组元素是数字,则进行拼接
    endStr += item
    // 修改最后一个数组元素
    newArray.splice(endIndex, 1, endStr)
    } else {
    // 如果最后一个数组元素是运算符,则将当前项直接添加到数组
    newArray.push(item)
    }
    } else {
    // 如果当前项是运算符,则将当前项直接添加到数组
    newArray.push(item)
    }
    })
    // 将数字与运算符遍历,将字符串类型的数字转换成数字类型
    newArray = newArray.map((item) => (isNumber(item) ? parseFloat(item) : item))
    // 合并一下小数点
    let newData = getDecimals(newArray)
    let num = sumResutl(newData)
    return num
    }

    // 引用案例
    // 先在需要用的地方引入compute函数
    // let template = '20+15.3+{a}/{b}-2*3.0'
    // 调用函数
    // console.log(compute(template,{a:2,b:1}))

  • 相关阅读:
    Docker 中国官方镜像加速
    mysql主从同步
    hadoop相关
    Mac上Ultra Edit的激活
    ansible安装应用软件
    Docker学习第二天-容器
    wwnjld团队第二轮迭代成员分数
    第二轮迭代发布报告
    wwnjld第二轮迭代测试报告
    12.24会议记录
  • 原文地址:https://www.cnblogs.com/elink/p/15742447.html
Copyright © 2011-2022 走看看