在工作中經常需要進行數字運算,當然也會遇到浮點型數字的運算,但是運算結果卻並不是想要。

這種小孩子都會做的簡單運算,強大的計算居然算算錯?原來,計算機的運算都需要轉成二制運算,而二進制和實現位數限制有些數無法有限表示。
比如:以下是十進制小數對應的二進制表示
0.1 >> 0.0001 1001 1001 1001…(1001無限循環) 0.2 >> 0.0011 0011 0011 0011…(0011無限循環
計算機里每種數據類型的存儲是一個有限寬度,比如 JavaScript 使用 64 位存儲數字類型,因此超出的會舍去。舍去的部分就是精度丟失的部分。
那小數計算會有問題,那把數字轉整數來計算不就可以了嗎?
/* ===== 浮點型數據的加、減、乘、除 ===== */
function add(arg1, arg2) { // 加法
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
}
function 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 ((arg1 * m - arg2 * m) / m).toFixed(n)
}
function mul(arg1, arg2) { // 乘法
let m = 0
let s1 = arg1.toString()
let 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)
}
function div(arg1, arg2) { // 除法
let t1 = 0
let t2 = 0
let r1
let r2
try {
t1 = arg1.toString().split('.')[1].length
} catch (e) {
}
try {
t2 = arg2.toString().split('.')[1].length
} catch (e) {
}
r1 = Number(arg1.toString().replace('.', ''))
r2 = Number(arg2.toString().replace('.', ''))
let intDiv = r1 / r2
let pow = Math.pow(10, t2 - t1)
return mul(intDiv, pow) // 這里用上面定義好的乘法運算
}
/* ===== 浮點型數據的加、減、乘、除 ===== */
