Appearance
金额计算
decimal.js(推荐)
ts
import Decimal from 'decimal.js'
export const subtraction = (a: number, b: number) => {
const numberA = Number(a)
const numberB = Number(b)
if (isNaN(numberA) || isNaN(numberB)) throw new Error('参数必须是数字')
return new Decimal(a).minus(new Decimal(b)).toNumber()
}自己实现
js
function getDecimalLength(num: number): number {
// 处理科学计数法
const numStr = num.toString()
if (numStr.includes('e')) {
const [base, exponent] = numStr.split('e')
const baseDecimals = base.includes('.') ? base.split('.')[1].length : 0
return Math.max(0, baseDecimals - Number(exponent))
}
// 普通小数
const decimal = numStr.split('.')[1]
return decimal ? decimal.length : 0
}
/**
* 减法
*/
export const subtraction = (a: number, b: number) => {
const numberA = Number(a)
const numberB = Number(b)
if (isNaN(numberA) || isNaN(numberB)) throw new Error('参数必须是数字')
const a_decimal = getDecimalLength(a)
const b_decimal = getDecimalLength(b)
const max_decimal = Math.max(a_decimal, b_decimal)
// 检查是否会超出安全整数范围
const maxSafeInteger = Number.MAX_SAFE_INTEGER
const factor = 10 ** max_decimal
if (Math.abs(a * factor) > maxSafeInteger || Math.abs(b * factor) > maxSafeInteger) {
// 超出安全范围时使用字符串处理或抛出错误
throw new Error('数字超出安全计算范围')
}
const a_plus = Math.round(a * factor) // 使用 Math.round 避免乘法精度问题
const b_plus = Math.round(b * factor)
return (a_plus - b_plus) / factor
}
/**
* 加法
*/
export const addition = (a: number, b: number) => {
const numberA = Number(a)
const numberB = Number(b)
if (isNaN(numberA) || isNaN(numberB)) throw new Error('参数必须是数字')
const a_decimal = getDecimalLength(a)
const b_decimal = getDecimalLength(b)
const max_decimal = Math.max(a_decimal, b_decimal)
// 检查是否会超出安全整数范围
const maxSafeInteger = Number.MAX_SAFE_INTEGER
const factor = 10 ** max_decimal
if (Math.abs(a * factor) > maxSafeInteger || Math.abs(b * factor) > maxSafeInteger) {
throw new Error('数字超出安全计算范围')
}
const a_plus = Math.round(a * factor)
const b_plus = Math.round(b * factor)
return (a_plus + b_plus) / factor
}
/**
* 乘法
*/
export const multiplication = (a: number, b: number) => {
const numberA = Number(a)
const numberB = Number(b)
if (isNaN(numberA) || isNaN(numberB)) throw new Error('参数必须是数字')
const a_decimal = getDecimalLength(a)
const b_decimal = getDecimalLength(b)
const total_decimal = a_decimal + b_decimal
// 检查是否会超出安全整数范围
const maxSafeInteger = Number.MAX_SAFE_INTEGER
const factor = 10 ** total_decimal
if (Math.abs(a * factor) > maxSafeInteger || Math.abs(b * factor) > maxSafeInteger) {
throw new Error('数字超出安全计算范围')
}
const a_plus = Math.round(a * 10 ** a_decimal)
const b_plus = Math.round(b * 10 ** b_decimal)
return (a_plus * b_plus) / factor
}
/**
* 除法
*/
export const division = (a: number, b: number) => {
const numberA = Number(a)
const numberB = Number(b)
if (isNaN(numberA) || isNaN(numberB)) throw new Error('参数必须是数字')
if (numberB === 0) throw new Error('除数不能为0')
const a_decimal = getDecimalLength(a)
const b_decimal = getDecimalLength(b)
const max_decimal = Math.max(a_decimal, b_decimal)
// 检查是否会超出安全整数范围
const maxSafeInteger = Number.MAX_SAFE_INTEGER
const factor = 10 ** max_decimal
if (Math.abs(a * factor) > maxSafeInteger || Math.abs(b * factor) > maxSafeInteger) {
throw new Error('数字超出安全计算范围')
}
const a_plus = Math.round(a * factor)
const b_plus = Math.round(b * factor)
return a_plus / b_plus
}
/**
* 数字计算工具类
*/
export class Calculator {
private value: number
constructor(initialValue: number = 0) {
this.value = initialValue
}
/**
* 实现 Symbol.toPrimitive 接口
* 使得 Calculator 实例可以直接参与数值运算
*/
[Symbol.toPrimitive]() {
return this.value
}
/**
* 快速创建计算器实例
*/
static from(initialValue: number): Calculator {
return new Calculator(initialValue)
}
/**
* 快速计算: 加法
*/
static add(a: number, b: number): number {
return addition(a, b)
}
/**
* 快速计算: 减法
*/
static subtract(a: number, b: number): number {
return subtraction(a, b)
}
/**
* 快速计算: 乘法
*/
static multiply(a: number, b: number): number {
return multiplication(a, b)
}
/**
* 快速计算: 除法
*/
static divide(a: number, b: number): number {
return division(a, b)
}
/**
* 加法
*/
add(num: number): Calculator {
this.value = addition(this.value, num)
return this
}
/**
* 减法
*/
subtract(num: number): Calculator {
this.value = subtraction(this.value, num)
return this
}
/**
* 乘法
*/
multiply(num: number): Calculator {
this.value = multiplication(this.value, num)
return this
}
/**
* 除法
*/
divide(num: number): Calculator {
this.value = division(this.value, num)
return this
}
/**
* 获取结果
*/
getValue(): number {
return this.value
}
/**
* 重置计算器
*/
reset(num: number = 0): Calculator {
this.value = num
return this
}
}