반응형

 

안녕하세요. 3년차 프론트엔드 개발자 김준영이라고 합니다.

고객들의 돈이 오가는 서비스를 개발하다 보면 서버에서 값을 받아 aggregation 하여 화면에 금액이나 수량을 표시해 주는 상황이 많이 생기게 됩니다. 자바스크립트에서는 0.1+0.2 !== 0.3인 문제가 있기 때문에 이와 같은 정확도 문제를 해결하기 위해서 bignumber.js, big.js, decimal.js와 같은 정밀 계산 라이브러리를 많이 사용하게 됩니다. 하지만 실무에서 해당 라이브러리들을 사용해 보면서 조금 아쉬운 포인트들이 있었고, 아래와 문제들을 좀 더 개선한 오픈소스를 만들어보자는 생각이 들었습니다..!

- 계산할 때마다 new 생성자를 사용해야 하는 점을 어떻게 개선할 수 있을까?
- 0.000001보다 작은 수는 왜 string type의 지수표현식으로 반환될까? (ex : new Big(0.0000001).valueOf() => "1e-7")
- add, sub, mul, div와 같은 메서드들에서 single parameter가 아닌 rest parameter 방식으로 값을 받게 할 수는 없을까?

이러한 포인트들을 개선하기 위해서 big.js를 활용하여 @ma9pie/math라는 계산 유틸 라이브러리를 개발하였습니다. 내부적으로 계산은 big.js로 처리하고 DX(Developer Experience)에 좀 더 중점을 두었습니다.

 

📦 Install

npm i @ma9pie/math

 

🕹 Use

import { math } from '@ma9pie/math';

math(1).add(2).sub(3).value(); // 0
math(10).add(5).sub(7).mul(2).div(4).value(); // 4

value
value() => string
returns calculated value as string.

math(1000).value(); // '1000'
math('1e7').value(); // '10000000'
math(1e-7).value(); // '0.0000001'

toNumber
toNumber() => number
returns calculated value as number.

math(1000).toNumber(); // 1000
math('1e7').toNumber(); // 10000000
math(1e-7).toNumber(); // 1e-7

add
.add(n) => Big n : number | string | BigInt
returns the current value added by n. 
if the n is invalid, it is treated as 0.

0.1 + 0.2, // 0.30000000000000004
math(0.1).add(0.2).value(); // '0.3'
math(1).add(2).add(3).value(); // '6'
math(1).add(2, 3, 4).value(); // '10'

sub
.sub(n) => Big n : number | string | BigInt
returns the current value subtracted by n. 
if the n is invalid, it is treated as 0.

0.3 - 0.1, // 0.19999999999999998
math(0.3).sub(0.1).value(); // '0.2'
math(1).sub(2).sub(3).value(); // '-4'
math(1).sub(2, 3, 4).value(); // '-8'

mul
.mul(n) => Big n : number | string | BigInt
returns the current value multiplied by n. 
if the n is invalid, it is treated as 0.

0.6 * 3, // 1.7999999999999998
math(0.6).mul(3).value(); // '1.8'
math(2).mul(2).mul(2).value(); // '8'
math(2).mul(2, 2, 2).value(); // '16'

div
.div(n) => Big n : number | string | BigInt
returns the current value divided by n. 
if the n is invalid, it is treated as 0.

355 / 113, // 3.1415929203539825
math(355).div(113).value(); // '3.141592920353982300'
math(10).div(3).value(); // '3.333333333333333333'
math(1000).div(10, 10, 10).value(); // '1'

abs
.abs() => Big returns the absolute current value.

math(-0.8).abs().value(); // '0.8'

pow
.pow(n) => Big n : number | string | BigInt
returns the current value nth power. 
if the n is invalid, it is treated as 0.

0.7 ** 2, // 0.48999999999999994
Math.pow(0.7, 2); // 0.48999999999999994
math(0.7).pow(2).value(); // '0.49'

eq
.eq(n) => boolean n : number | string | BigInt
returns whether the current value and n are the same.

0.1 + 0.2 === 0.3, // false
math(0.1).add(0.2).eq(0.3); // true
math('0.0000001').eq(1e-7); // true
math(1e7).eq(10000000); // true

gt
.gt(n) => boolean n : number | string | BigInt
returns whether the current value is greater than n.

0.1 + 0.2 > 0.3, // true
math(0.1).add(0.2).gt(0.3); // false

gte
.gte(n) => boolean n : number | string | BigInt
returns whether the current value is greater than or equal to n.

0.1 + 0.2 <= 0.3, // false
math(0.1).add(0.2).gte(0.3); // true

lt
.lt(n) => boolean n : number | string | BigInt
returns whether the current value is less than n.

0.1 + 0.2 > 0.3, // true
math(0.1).add(0.2).lt(0.3); // false

lte
.lte(n) => boolean n : number | string | BigInt
returns whether the current value is less than or equal to n.

0.1 + 0.2 <= 0.3, // false
math(0.1).add(0.2).lte(0.3); // true

isZero
.isZero() => boolean
returns whether the current value is 0.

math(0).isZero(); // true
math(-0).isZero(); // true
math(0.0).isZero(); // true
math('0').isZero(); // true
math('-0').isZero(); // true
math(Number.MIN_SAFE_INTEGER).isZero(); // false
math(Number.MAX_SAFE_INTEGER).isZero(); // false

 

🔍 Test

npm run test

 

 

git : https://github.com/ma9pie/math
npm : https://www.npmjs.com/package/@ma9pie/math



감사합니다!

반응형

+ Recent posts