美文网首页
js数值精确计算及科学计数法格式化

js数值精确计算及科学计数法格式化

作者: 火锅伯南克 | 来源:发表于2020-01-15 15:49 被阅读0次

cale.js

function getReg(s){
  return [
    {
      val: s.match(/^(\d+)\.(\d+)e\-(\d+)$/),
      f(){
        //["1.25e-21", "1", "25", "21"]
        let m = this.val
        return {
          value: + (m[1] + m[2]),
          order: ~ (+m[3] + m[2].length) + 1,
          other: m
        }
      }
    },
    {
      val: s.match(/^(\d+)\.(\d+)e\+(\d+)$/),
      f(){
        //["1.25e+21", "1", "25", "21"]
        let m = this.val
        return {
          value: + (m[1] + m[2]),
          order: m[3] - m[2].length,
          other: m
        }
      }
    },
    {
      val: s.match(/^(\d+)e\-(\d+)$/),
      f(){
        //["1e-21", "1", "21"]
        let m = this.val
        return {
          value: + m[1],
          order: ~ m[2] + 1,
          other: m
        }
      }
    },
    {
      val: s.match(/^(\d+)e\+(\d+)$/),
      f(){
        //["1e+21", "1", "21"]
        let m = this.val
        return {
          value: + m[1],
          order: + m[2],
          other: m
        }
      }
    },
    {
      val: s.match(/^(\d+)\.(\d+)$/),
      f(){
        //["1.21", "1", "21"]
        let m = this.val
        return {
          value: + (m[1] + m[2]),
          order: ~ m[2].length + 1,
          other: m
        }
      }
    },
    {
      val: s.match(/^\d+$/),
      f(){
        //["126"]
        let m = this.val
        return {
          value: + m[0],
          order: 0,
          other: m
        }
      }
    },
  ]
}
export default {
  install (Vue, option) {
    Object.defineProperty(Number.prototype, 'str', {
      value: function (){
        let pad = function(num){
          let len = num.other.length === 3 ? 0 : num.other[2].length
          if(num.order < 0){// 10的指数
            return `0.${''.padEnd(~ num.order - len, 0)}${num.value}`
          }else{
            return `${num.value}${''.padEnd(num.order, 0)}`
          }
        }
        let s = this.toString();
        //后2个对结果有影响,所以去掉
        const obj = getReg(s).slice(0, 4);
        for(let i = 0;i < obj.length; i++){
          if(obj[i].val){
            return pad(obj[i].f())
          }
        }
        return s
      }
    });
    Vue.prototype.$n = {
      //格式化数字
      filter: function(n){
        if(typeof n !== 'number'){
          console.warn(`某个值不为number类型,${n}`)
          n = parseFloat(n)
        };
        let s = n.toString();
        const obj = getReg(s);
        for(let i = 0;i < obj.length; i++){
          if(obj[i].val){
            return obj[i].f()
          }
        }
      },
      max(all){
        return Math.max.apply(null, all.map((item) => {
          return item.order
        }));
      },
      min(all){
        return Math.min.apply(null, all.map((item) => {
          return item.order
        }));
      },
      //提供计算必要的数值信息
      getChild(arr){
        //过滤后数组
        let all = arr.map((item) => {
          return this.filter(item)
        })
        //获取最大阶数
        let max = this.max(all)
        //获取最小阶数
        let min = this.min(all)
        return { arr, all, max, min }
      },
      //加法
      add(...arg){
        let { all, min } = this.getChild(arg);
        let num = all.reduce((total, item)=>{
          return total + item.value * 10 ** (item.order + Math.abs(min))
        }, 0);
        return num / 10 ** Math.abs(min)
      },
      //减法
      sub(...arg){
        let { all, min } = this.getChild(arg);
        let num = all.reduce((total, item, i)=>{
          i == 1 && (total = total.value * 10 ** (total.order + Math.abs(min)))
          return total - item.value * 10 ** (item.order + Math.abs(min))
        });
        return num / 10 ** Math.abs(min)
      },
      //乘法
      mul(...arg){
        let { all } = this.getChild(arg);
        let num = all.reduce((total, item)=>{
          return {
            value: total.value * item.value,
            order: total.order + item.order
          }
        }, { value: 1, order: 0 });
        if(num.order < 0){
          return num.value / 10 ** (~num.order + 1)
        }
        return num.value * 10 ** num.order
      },
      //除法
      div(...arg){
        let { arr, all, max, min } = this.getChild(arg);
        //可以自定义返回,如果有除数或者被除数为0返回的值
        if(arr.includes(0)) {
          console.warn(`除数或者被除数为 0,以返回 1 处理`)
          return 1
        }
        let num = all.reduce((total, item)=>{
          let min = Math.abs(this.min([total, item]));
          let num = (total.value * 10 ** (total.order + min)) / (item.value * 10 ** (item.order + min))
          return this.filter(num)
        })
        if(num.order < 0){
          return num.value / 10 ** (~num.order + 1)
        }
        return num.value * 10 ** num.order
      }
    }
  }
}

main.js

import cale from '@/plugin/cale.js';
Vue.use(cale);

用法

mounted(){
    console.log(this.$n.add(0.2, 0.1)) //0.3
    console.log(this.$n.mul(0.3, 0.2, .06, 0.8,0.7,0.7,0.7)) //0.00098784
    console.log(this.$n.mul(1.25e+25,'1.25e-25')) //1.5625
    let a = this.$n.div(1.25e+25,'1.24e-25') //1.0080645161290322e+50
    let b = a.str() // 100806451612903220000000000000000000000000000000000
  },

相关文章

  • js数值精确计算及科学计数法格式化

    cale.js main.js 用法

  • 一次重大损失后的教训总结

    1、JS当小数位超过6位就会变成科学计数法,PHP接到科学计数进行bcmul计算结果是0 2、php+mysql会...

  • 2018-04-03

    一次重大损失后的教训总结 1、JS当小数位超过6位就会变成科学计数法,PHP接到科学计数进行bcmul计算结果就是...

  • 【18-03-23】Matlab 基础概念

    1° 计算的介绍 数值默认为双精度实数,可用浮点数或科学计数法表示。浮点数表示范围在 10^-308 ~ 10^3...

  • BigDecimal详解

    float和double设计的目的是为了科学计算和工程计算. 它提供在广域数值范围上较为精确的快速计算. 然而,它...

  • BigDecimal的详细解析

    前言 float和double设计的目的是为了科学计算和工程计算. 它提供在广域数值范围上较为精确的快速计算. 然...

  • BigDecimal运算详细解析

    float和double设计的目的是为了科学计算和工程计算. 它提供在广域数值范围上较为精确的快速计算. 然而,它...

  • 2022-03-10 Warning messages: 1:

    用了各种方法都没能把矩阵转换成数值型的解决方案。 一开始数据内容里有科学计数法的“e”,用 设置默认不用科学计数法...

  • Python基础代码的学习

    基础输入输出 精确计算 数值转换与计算 列表基础 列表提高 可变序列及列表通用操作 猜数字游戏

  • JS数值

    数值 100 整型 3.14 浮点型 3.14e7 科学计数法 0xfa1b 16进制 在数值中除了加减乘除求余外...

网友评论

      本文标题:js数值精确计算及科学计数法格式化

      本文链接:https://www.haomeiwen.com/subject/lpmtzctx.html