JS:部分高精度数学计算(限自然数)

/**
 * 说明:自定义的 高精度数学计算 的静态方法(限正整数)
 * 注意:参数说明开头若已'(xxx)'开头表示默认值
 * 注意:所有参数必须转为String,不可使用Number
 * 注意:所有方法均不会返回Number类型、浮点数形式
 */
const BCMathInteger = new Object()
Object.assign(BCMathInteger, {
  /**
   * 加法运算
   * @param {String} a
   * @param {String} b
   * @returns {String}
   */
  add: function (a, b) {
    const al = a.length
    const bl = b.length
    const r = []
    let i = 0
    if (al < bl) {
      a = "0".repeat(bl - al) + a
      for (; i < bl; i++) r[i] = (a[i] ^ 0) + (b[i] ^ 0)
    } else {
      b = "0".repeat(al - bl) + b
      for (; i < al; i++) r[i] = (a[i] ^ 0) + (b[i] ^ 0)
    }
    for (i--; i > 0; i--) if (r[i] > 9) r[i] %= 10, r[i - 1]++
    return r.join("")
  },
  /**
   * 自增运算
   * @param {String} n
   * @returns {String}
   */
  addAuto: function (n) {
    let r = n.split(""), i = a.length
    r[--i]++
    while (i > 0 && r[i] === 10) r[i] = 0, r[--i]++
    return r.join("")
  },
  /**
   * 计算两数的平均值
   * @param {String} a
   * @param {String} b
   * @returns {String}
   */
  avg: function (a, b) {
    return this.div(this.add(a, b), "2")
  },
  /**
   * 计算立方根:牛顿迭代法
   * @param {String} n
   * @returns {String}
   */
  cbrt: function (n) {
    let i = this.enum(Math.cbrt(a)), j = this.div(a, this.mul(i, i))
    while (this.abs(this.sub(i, j)) > 1) {
      i = j
      j = this.div(this.add(i, this.div(a, this.mul(i, i))), "2")
    }
    return i
  },
  /**
   * 除法运算
   * @param {String} a
   * @param {String} b
   * @returns {String}
   */
  div: function (a, b) {
    let al = a.length, bl = b.length
    if (al < bl || al === bl && a < b) return "0"
    let r = this.enum(a / b), n
    a = this.sub(a, this.mul(r, b))
    while (a < 0 || al > bl || al === bl && a >= b) {
      n = this.enum(a / b)
      if (a[0] === "-") {
        r = this.sub(r, n)
        a = this.sub(this.mul(b, n), a.substr(1))
      } else {
        r = this.add(r, n)
        a = this.sub(a, this.mul(b, n))
      }
      al = a.length
    }
    return r
  },
  /**
   * 求两数的最大公约数:均会强制转整
   * @param {String} a
   * @param {String} b
   * @returns {String}
   */
  gcd: function (a, b) {
    return b == 0 ? a : this.gcd(b, this.mod(a, b))
  },
  /**
   * 判断前数能否被后数除尽
   * @param {String} a 被除数
   * @param {String} b 除数
   * @returns {Boolean}
   */
  isDivisible: function (a, b) {
    a = this.mod(a, b)
    let num = {}
    while (a !== "0" && !(a in num)) {
      num[a] = true
      a = this.mod(a + "0", b)
    }
    return a === "0"
  },
  /**
   * 判断前数是否大于等于后数
   * @param {String} a
   * @param {String} b
   * @returns {Boolean}
   */
  isGreater: function (a, b) {
    const al = a.length
    const bl = b.length
    return al > bl || al === bl && a >= b
  },
  /**
   * 判断前数是否小于等于后数
   * @param {String} a
   * @param {String} b
   * @returns {Boolean}
   */
  isSmaller: function (a, b) {
    const al = a.length
    const bl = b.length
    return al < bl || al === bl && a <= b
  },
  /**
   * 求两数的最小公倍数
   * @param {String} a
   * @param {String} b
   * @returns {String}
   */
  lcm: function (a, b) {
    return this.div(this.mul(a, b), this.gcd(a, b))
  },
  /**
   * 获取两数中的最大值
   * @param {String} a
   * @param {String} b
   * @returns {String}
   */
  max: function (a, b) {
    const al = a.length
    const bl = b.length
    return (al < bl || al === bl && a < b) ? b : a
  },
  /**
   * 获取两数中的最小值
   * @param {String} a
   * @param {String} b
   * @returns {String}
   */
  min: function (a, b) {
    const al = a.length
    const bl = b.length
    return (al < bl || al === bl && a < b) ? a : b
  },
  /**
   * 求模运算
   * @param {String} a 被除数
   * @param {String} b 除数
   * @returns {String}
   */
  mod: function (a, b) {
    let al = a.length, bl = b.length, m, n
    while (al > bl || al === bl && a >= b) {
      m = this.mul(b, this.enum(a / b))
      ml = m.length
      a = (al > ml || al === ml && a > m) ? this.sub(a, m) : (n = !n, this.sub(m, a))
      al = a.length
    }
    return n && a > 0 ? this.sub(b, a) : a
  },
  /**
   * 乘法运算
   * @param {String} a
   * @param {String} b
   * @returns {String}
   */
  mul: function (a, b) {
    const al = a.length
    const bl = b.length
    const r = []
    let k = al + bl - 2, j, i = k
    for (; i >= 0; i--) r[i] = 0
    // 由于系统数字过大会失去精度,所以以下算法必须采用高精度
    for (i = 0; i < al; i++) for (j = 0; j < bl; j++) r[i + j] = this.add(r[i + j], a[i] * b[j])
    for (i = k; i > 0; i--) {
      r[i - 1] = this.add(r[i - 1], r[i].substr(0, r[i].length - 1))
      r[i] = r[i].substr(-1)
    }
    return r.join("")
  },
  /**
   * 指数运算
   * @param {String} a 底数
   * @param {String} b 指数
   * @returns {String}
   */
  pow: function (a, b) {
    let key = ["1"], pow = [a], i = 1, n = "2"
    for (; this.isGreater(b, n); i++) {
      key[i] = n
      pow[i] = a = this.mul(a, a)
      n = this.mul(n, 2)
    }
    b = this.sub(b, key[--i])
    for (i--; i >= 0; i--) if (this.isGreater(b, key[i])) {
      a = this.mul(a, pow[i])
      b = this.sub(b, key[i])
    }
    return a
  },
  /**
   * 返回两数之间的随机整数
   * @param {String} a
   * @param {String} b
   * @returns {String}
   */
  rand: function (a, b) {
    a = this.mul(a, Math.random() * 1e18 + "")
    return a.substr(0, a.length - 18) || "0"
  },
  /**
   * 返回两数之间的随机数
   * @param {String} a
   * @param {String} b
   * @returns {String}
   */
  random: function (a, b) {
    let i = this.sub(b, a);
    if (i[0] === "-") a = b, i = i.substr(1)
    b = this.mul(this.add(i, "1"), Math.random() * 1e18 + "")
    return this.add(a, b.substr(0, b.length - 18))
  },
  /**
   * 计算平方根:牛顿迭代法法
   * @param {String} n
   * @returns {String}
   */
  sqrt: function (n) {
    let i = this.enum(Math.sqrt(n)), j = this.div(n, i)
    while (this.abs(this.sub(i, j)) > 1) {
      i = j
      j = this.div(this.add(i, this.div(a, i)), "2")
    }
    return i
  },
  /**
   * 减法运算
   * @param {String} a
   * @param {String} b
   * @returns {String}
   */
  sub: function (a, b) {
    const al = a.length
    const bl = b.length
    const r = []
    let i = 0
    if (al < bl) {
      a = "0".repeat(bl - al) + a
      for (; i < bl; i++) r[i] = a[i] - b[i]
    } else {
      b = "0".repeat(al - bl) + b
      for (; i < al; i++) r[i] = a[i] - b[i]
    }
    for (i--; i > 0; i--) if (r[i] < 0) r[i] += 10, r[i - 1]--
    return r.join("").replace(/^0+/, "") || "0"
  },
  /**
   * 自减运算
   * @param {String} n
   * @returns {String}
   */
  subAuto: function (n) {
    let r = a.split(""), i = a.length
    r[--i]--
    while (i > 0 && r[i] === -1) r[i] = 9, r[--i]--
    return r.join("")
  },
  /**
   * 把任意形式的数字(限正数)转为10进制的字符串数字
   * @param {String} n
   * @returns {String}
   */
  toDec: function (n) {
    n = (n + '').split('e+')
    if (n[1]) {
      const a = n[0].split('.')
      return a[1] ? a[0] + a[1] + '0'.repeat(n[1] - a[1].length) : a[0] + '0'.repeat(n[1])
    }
    return n[0]
  },
})

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值