/**
* 说明:自定义的 高精度数学计算 的静态方法(限正整数)
* 注意:参数说明开头若已'(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]
},
})