Skip to content

Commit

Permalink
feat(Calculator): 支持四则运算
Browse files Browse the repository at this point in the history
  • Loading branch information
fjc0k committed Feb 14, 2022
1 parent 151290e commit 0fde095
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 42 deletions.
14 changes: 14 additions & 0 deletions src/utils/Calculator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,20 @@ describe('Calculator', () => {
})
})

describe('四则运算', () => {
test('ok', () => {
expect(
// 1+3*2+10/(5-1-2)-6
Calculator.add(
1,
_ => _.mul(3, 2),
_ => _.div(10, _.sub(5, 1, 2)),
-6,
),
).toBe(6)
})
})

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', () => {
Expand Down
115 changes: 73 additions & 42 deletions src/utils/Calculator.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import DecimalLight, { Config } from 'decimal.js-light'
import DecimalLight, { Config, Numeric } from 'decimal.js-light'

export interface CalculatorInstance {
export type CalculatorPrimitiveValue = Numeric

export type CalculatorValue =
| CalculatorPrimitiveValue
| ((calculator: CalculatorInstance<DecimalLight>) => DecimalLight)

export interface CalculatorInstance<T = number> {
/**
* decimal.js 引用。
*/
Expand All @@ -23,7 +29,7 @@ export interface CalculatorInstance {
*
* @param values 加数列表
*/
add(...values: number[]): number
add(...values: CalculatorValue[]): T
/**
* 减。
*
Expand All @@ -32,7 +38,7 @@ export interface CalculatorInstance {
*
* @param values 减数列表
*/
sub(...values: number[]): number
sub(...values: CalculatorValue[]): T
/**
* 乘。
*
Expand All @@ -41,7 +47,7 @@ export interface CalculatorInstance {
*
* @param values 乘数列表
*/
mul(...values: number[]): number
mul(...values: CalculatorValue[]): T
/**
* 除。
*
Expand All @@ -50,62 +56,87 @@ export interface CalculatorInstance {
*
* @param values 除数列表
*/
div(...values: number[]): number
div(...values: CalculatorValue[]): T
/**
* 转换为数字。
*
* @param value 值
*/
toNumber(value: CalculatorPrimitiveValue): T
}

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

const getValue = (value: CalculatorValue) =>
typeof value === 'function'
? value({
...Calculator,
toNumber: (value: any) => new Decimal(value),
} as any as CalculatorInstance<DecimalLight>)
: value

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()
return this.toNumber(
values.length === 0
? 0
: values.length === 1
? getValue(values[0])
: values.reduce<DecimalLight>(
(res, value) => res.add(getValue(value)),
new Decimal(0),
),
)
},
sub(...values) {
return values.length === 0
? 0
: values.length === 1
? values[0]
: values
.reduce(
return this.toNumber(
values.length === 0
? 0
: values.length === 1
? getValue(values[0])
: values.reduce<DecimalLight>(
(res, value, index) =>
index === 0 ? res.add(value) : res.sub(value),
index === 0
? res.add(getValue(value))
: res.sub(getValue(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()
return this.toNumber(
values.length === 0
? 0
: values.length === 1
? getValue(values[0])
: values.reduce<DecimalLight>(
(res, value) => res.mul(getValue(value)),
new Decimal(1),
),
)
},
div(...values) {
return values.length === 0
? 0
: values.length === 1
? values[0]
: values
.reduce(
return this.toNumber(
values.length === 0
? 0
: values.length === 1
? getValue(values[0])
: values.reduce<DecimalLight>(
(res, value, index) =>
index === 0 ? res.add(value) : res.div(value),
index === 0
? res.add(getValue(value))
: res.div(getValue(value)),
new Decimal(0),
)
.toDecimalPlaces(config?.decimalPlaces)
.toNumber()
),
)
},
toNumber(value) {
return new Decimal(value)
.toDecimalPlaces(config?.decimalPlaces)
.toNumber()
},
}

Expand Down

0 comments on commit 0fde095

Please sign in to comment.