JsLib/NumberVal.js

/*
 * @Author: your name
 * @Date: 2021-08-26 18:30:42
 * @LastEditTime: 2021-09-07 15:38:26
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \npm\src\NumberVal\NumberVal.js
 */
/**
 * 数值计算类
 *
 * @class NumberVal
 */
class NumberVal {
  constructor() {}

  /**
   * @description 打印开始点
   *
   * @memberof NumberVal
   */
  start() {
    console.log("NumberVal start^_^_^_^_^_^_^_^_^_^")
  }

  /**
   * @description 打印结束点
   *
   * @memberof NumberVal
   */
  end() {
    console.log("NumberVal end^_^_^_^_^_^_^_^_^_^")
  }

  /**
   * @description 平均数
   *
   * @param {} nums 多个参数 (1, 2, 3)
   * @return {Number} 平均数
   * @memberof NumberVal
   * @example
   * average(...[1, 2, 3])  // 2
   * average(1, 2, 3)  // 2
   */
  average(...nums) {
    return nums.reduce((acc, val) => acc + val, 0) / nums.length
  }

  /**
   * @description 思路:
   * @description 1. fn如果是函数,通过map,即可拿到对象中的属性,再通过reduce将map循环的值累加
   * @description 2. fn如果是字符串,通过map的参数val,拿到每一个对象,对象[fn]可拿到对应的值(fn此时是字符串),再通过reduce将map循环的值累加
   *
   * @description 数组对象属性平均数
   *
   * @param {Array} arr 目标数组
   * @param {*} fn 可以是函数、也可以是数组中对象的属性名
   * @return {Number}  平均数
   * @memberof NumberVal
   * @example
   * averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], o => o.n)  // 5
   * averageBy([{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }], 'n')  // 5
   */
  averageBy(arr, fn) {
    return (
      arr
        .map(typeof fn === "function" ? fn : (val) => val[fn])
        .reduce((acc, val) => acc + val, 0) / arr.length
    )
  }

  /**
   * @description 生成指定范围随机数
   * @param {number } min
   * @param {number} max
   * @return {Number}
   * @memberof NumberVal
   * @example
   * RandomNum(0,10)  // 5
   */
  RandomNum(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min
  }

  /**
   * @description 生成指定范围的随机小数
   *
   * @param {number} min 最小值
   * @param {number} max 最大值
   * @return {number}
   * @memberof NumberVal
   * @example
   * randomNumberInRange(0,10)  // 5.041143990814554
   */
  randomNumberInRange(min, max) {
    return Math.random() * (max - min) + min
  }

  /**
   * @description 生成随机整数(支持一个参数或者两个参数)
   *
   * @param {Number} min 最小值
   * @param {Number} max 最大值
   * @return {Number}
   * @memberof NumberVal
   * @example
   * randomNumInteger(10) // 5
   * randomNumInteger(10,20)  // 15
   */
  randomNumInteger(min, max) {
    switch (arguments.length) {
      case 1:
        return parseInt(Math.random() * min + 1, 10)
      case 2:
        return parseInt(Math.random() * (max - min + 1) + min, 10)
      default:
        return 0
    }
  }

  /**
   * @description 加法函数(精度丢失问题)
   * @param {Number} arg1
   * @param {Number} arg2
   * @return {Number}
   * @memberof NumberVal
   * @example
   * add(0.1,0.2)  // 0.3
   */
  add(arg1, arg2) {
    // 还有解决方式:把小数放到位整数(乘倍数),再缩小回原来倍数(除倍数)
    // 0.1 + 0.2  ->  (0.1*10 + 0.2*10) / 10 == 0.3   // true

    let 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
  }

  /**
   * @description 减法函数(精度丢失问题)
   * @param {Number} arg1
   * @param {Number} arg2
   * @return {Number}
   * @memberof NumberVal
   * @example
   * sub(0.2,0.1)  // 0.1
   */
  sub(arg1, arg2) {
    let r1, r2, m, n
    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))
    n = r1 >= r2 ? r1 : r2
    return Number(((arg1 * m - arg2 * m) / m).toFixed(n))
  }

  /**
   * @description 除法函数(精度丢失问题)
   *
   * @param {Number} num1
   * @param {Number} num2
   * @return {Number}
   * @memberof NumberVal
   * @example
   * division(0.2,0.1)  // 2
   */
  division(num1, num2) {
    let t1, t2, r1, r2
    try {
      t1 = num1.toString().split(".")[1].length
    } catch (e) {
      t1 = 0
    }
    try {
      t2 = num2.toString().split(".")[1].length
    } catch (e) {
      t2 = 0
    }
    r1 = Number(num1.toString().replace(".", ""))
    r2 = Number(num2.toString().replace(".", ""))
    return (r1 / r2) * Math.pow(10, t2 - t1)
  }

  /**
   * @description 乘法函数(精度丢失问题)
   *
   * @param {Number} num1
   * @param {Number} num2
   * @return {Number}
   * @memberof NumberVal
   * @example
   * mcl(0.2,0.1)  // 0.02
   */
  mcl(num1, num2) {
    let m = 0,
      s1 = num1.toString(),
      s2 = num2.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)
    )
  }

  /**
   * @description Math.round() 函数返回一个数字四舍五入后最接近的整数
   *
   * @description 四舍五入到指定位数
   *
   * @param {Number} n 数值
   * @param {number} [decimals=0] 指定位数
   * @return {Number}
   * @memberof NumberVal
   * @example
   * round(5.4585, 2) // 5.46
   */
  round(n, decimals = 0) {
    return Number(`${Math.round(`${n}e${decimals}`)}e-${decimals}`)
  }

  /**
   * @description 计算数组或多个数字的总和
   *
   * @param {Array} arr 目标数组
   * @return {Number}   总和
   * @memberof NumberVal
   * @example
   * sum(1, 2, 3, 4) // 10
   * sum(...[1, 2, 3, 4]) // 10
   */
  sum(...arr) {
    return [...arr].reduce((acc, val) => acc + val, 0)
  }

  /**
   * @description Intl.NumberFormat是对语言敏感的格式化数字类的构造器类(https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat)
   * 
   * @description  货币单位转换
   *
   * @param {Number} n 数值
   * @param {String} curr 货币格式
   * @param {*} [LanguageFormat=undefined] 语言 en-us | fa
   * @return {String} 
   * @memberof NumberVal
   * @example
   * toCurrency(123456.789, 'EUR') // €123,456.79
   * toCurrency(123456.789, 'USD', 'en-us') // $123,456.79
   * toCurrency(123456.789, 'USD', 'fa') // ‎$۱۲۳٬۴۵۶٫۷۹
   * toCurrency(322342436423.2435, 'JPY') // JP¥322,342,436,423
   */
  toCurrency(n, curr, LanguageFormat = undefined) {
    return Intl.NumberFormat(LanguageFormat, {
      style: "currency",
      currency: curr,
    }).format(n)
  }
}

export default NumberVal