Skip to content

Commit

Permalink
feat(Calculator): 可通过 make 创建新的计算器
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Feb 12, 2022
1 parent 5e6e393 commit cf1a02b
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 49 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
"cli-table3": "^0.6.0",
"cuid": "^2.1.8",
"date-fns": "^2.24.0",
"decimal.js": "^10.3.1",
"decimal.js-light": "^2.5.1",
"fast-xml-parser": "^3.18.0",
"ioredis": "^4.22.0",
"lodash-uni": "^1.1.0",
Expand Down
19 changes: 19 additions & 0 deletions src/utils/Calculator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,23 @@ describe('Calculator', () => {
expect(Calculator.div(0.69, 10)).toBe(0.069)
})
})

describe('银行家舍入法', () => {
// https://baike.baidu.com/item/%E9%93%B6%E8%A1%8C%E5%AE%B6%E8%88%8D%E5%85%A5/4781630?fr=aladdin
test('ok', () => {
expect(Calculator.make({ decimalPlaces: 2 }).add(9, 0.825)).toBe(9.83)
expect(
Calculator.make({
decimalPlaces: 2,
rounding: Calculator.decimal.ROUND_HALF_EVEN,
}).add(9, 0.825),
).toBe(9.82)
expect(
Calculator.make({
decimalPlaces: 2,
rounding: Calculator.decimal.ROUND_HALF_EVEN,
}).add(9, 0.82501),
).toBe(9.83)
})
})
})
130 changes: 83 additions & 47 deletions src/utils/Calculator.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
import Decimal from 'decimal.js'
import DecimalLight, { Config } from 'decimal.js-light'

/**
* 科学计算器。主要是为了避免 js 的浮点数精度计算问题。
*/
export class Calculator {
export interface CalculatorInstance {
/**
* decimal.js 引用。
*/
decimal: typeof DecimalLight
/**
* 根据配置创建一个新的计算器。
*
* @param config 配置
*/
make(
config?: Config & {
decimalPlaces?: number
},
): CalculatorInstance
/**
* 加。
*
Expand All @@ -12,14 +23,7 @@ export class Calculator {
*
* @param values 加数列表
*/
static add(...values: number[]): number {
return values.length === 0
? 0
: values.length === 1
? values[0]
: values.reduce((res, value) => res.add(value), new Decimal(0)).toNumber()
}

add(...values: number[]): number
/**
* 减。
*
Expand All @@ -28,20 +32,7 @@ export class Calculator {
*
* @param values 减数列表
*/
static sub(...values: number[]): number {
return values.length === 0
? 0
: values.length === 1
? values[0]
: values
.reduce(
(res, value, index) =>
index === 0 ? res.add(value) : res.sub(value),
new Decimal(0),
)
.toNumber()
}

sub(...values: number[]): number
/**
* 乘。
*
Expand All @@ -50,14 +41,7 @@ export class Calculator {
*
* @param values 乘数列表
*/
static mul(...values: number[]): number {
return values.length === 0
? 0
: values.length === 1
? values[0]
: values.reduce((res, value) => res.mul(value), new Decimal(1)).toNumber()
}

mul(...values: number[]): number
/**
* 除。
*
Expand All @@ -66,17 +50,69 @@ export class Calculator {
*
* @param values 除数列表
*/
static div(...values: number[]): number {
return values.length === 0
? 0
: values.length === 1
? values[0]
: values
.reduce(
(res, value, index) =>
index === 0 ? res.add(value) : res.div(value),
new Decimal(0),
)
.toNumber()
div(...values: number[]): number
}

const make: CalculatorInstance['make'] = config => {
const Decimal = DecimalLight.clone(config)

const Calculator: CalculatorInstance = {
decimal: DecimalLight,
make: make,
add(...values) {
return values.length === 0
? 0
: values.length === 1
? values[0]
: values
.reduce((res, value) => res.add(value), new Decimal(0))
.toDecimalPlaces(config?.decimalPlaces)
.toNumber()
},
sub(...values) {
return values.length === 0
? 0
: values.length === 1
? values[0]
: values
.reduce(
(res, value, index) =>
index === 0 ? res.add(value) : res.sub(value),
new Decimal(0),
)
.toDecimalPlaces(config?.decimalPlaces)
.toNumber()
},
mul(...values) {
return values.length === 0
? 0
: values.length === 1
? values[0]
: values
.reduce((res, value) => res.mul(value), new Decimal(1))
.toDecimalPlaces(config?.decimalPlaces)
.toNumber()
},
div(...values) {
return values.length === 0
? 0
: values.length === 1
? values[0]
: values
.reduce(
(res, value, index) =>
index === 0 ? res.add(value) : res.div(value),
new Decimal(0),
)
.toDecimalPlaces(config?.decimalPlaces)
.toNumber()
},
}

return Calculator
}

/**
* 科学计算器。主要是为了避免 js 的浮点数精度计算问题。
*/
export const Calculator = make()
7 changes: 6 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3444,7 +3444,12 @@ decamelize@^1.1.0, decamelize@^1.2.0:
resolved "https://registry.npm.taobao.org/decamelize/download/decamelize-1.2.0.tgz?cache=0&sync_timestamp=1610348726858&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdecamelize%2Fdownload%2Fdecamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=

decimal.js@^10.2.1, decimal.js@^10.3.1:
decimal.js-light@^2.5.1:
version "2.5.1"
resolved "https://registry.npmmirror.com/decimal.js-light/-/decimal.js-light-2.5.1.tgz#134fd32508f19e208f4fb2f8dac0d2626a867934"
integrity sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==

decimal.js@^10.2.1:
version "10.3.1"
resolved "https://registry.npmmirror.com/decimal.js/download/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783"
integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==
Expand Down

0 comments on commit cf1a02b

Please sign in to comment.