console.log(1-0.07)???
앞서 스왑(Token Transfers) 로그를 남기기 위해
이전데이터 값과 현재 컨트랙트 자산과의 차액 로그형태로 로직을 결정하기로 했다.
그런데,
DB update과정에서 연산처리 중
1 Ehter에서 0.07 Ether를 차감했더니 0.9299999999999999가 되었다?!
같은 맥락으로
0.1+0.2를 더하면 0.30000000000000004가 되는 것과 같은 문제다.
이는 블록체인 데이터의 산술처리 문제라기보다는
엄밀히 말하자면 프로그래밍 언어의 산술처리문제라 봐야 할 것 같다.
왜 이런 상황이 발생할까?
부동소수점 연산
모든 프로그래밍 언어는 부동 소수점 연산을 이진수로 처리한다.
이는 컴퓨터에서 실수를 이진 부동소수점 형태로 표현하는 방식 때문인데
사람의 10진법 표현방법을 컴퓨터는 2진수로 연산한 뒤에 사람의 10진법 형태로 표현하기 때문에
정확한 계산결과가 나오지 않는 경우가 발생하는 것.
https://gsmesie692.tistory.com/94
컴퓨터에서의 실수 표현: 고정소수점 vs 부동소수점
어제 트위터 타임라인을 보다가, '부동소수점' 이라는 단어를 보면 어떻게 해석하게 되느냐는 그런 트윗이 RT로 넘어왔다. 생각해보니까 굉장히 비직관적인 단어다.원래 영어단어는 floating point
gsmesie692.tistory.com
블록체인에서는 매우 큰 숫자들이 많이 사용되며,
일반적인 JavaScript의 Number 타입으로는 충분한 정확도를 보장할 수 없는 경우가 있다.
이런 경우에 BigNumber를 사용하여 정확한 정수 연산을 수행할 수 있다.
BigNumber를 사용해야 하는 이유
- 정확한 정수 연산: JavaScript의 Number 타입은 53비트로 제한되어 있어 더 큰 숫자의 경우 정확성을 보장할 수 없다.
- 부동 소수점 오차 방지: 앞의 예시처럼 JavaScript의 Number 타입은 부동 소수점 연산에서 정확성을 보장하지 않는다. 이로 인해 특정 연산에서 반올림 오차가 발생할 수 있으므로 정수 연산으로 오차를 방지할 수 있다.
- 큰 숫자 다루기: 블록체인에서는 트랜잭션 금액, 잔액, 토큰 수량 등 매우 큰 숫자들을 다루어야 한다. BigNumber는 이러한 큰 숫자들을 다루기 위해 필요하다.
//테스트코드
const contractInfo = {
targetDeposit: '1000000000000000000', // 예시 값
totalDeposit: '500000000000000000', // 예시 값
};
describe('Remaining Amount Calculation', () => {
test('Calculates remaining amount correctly', () => {
const targetDepositBN = web3.utils.toBN(contractInfo.targetDeposit);
const totalDepositBN = web3.utils.toBN(contractInfo.totalDeposit);
const remainingAmountBN = targetDepositBN.sub(totalDepositBN);
const remainingAmount = parseFloat(web3.utils.fromWei(remainingAmountBN));
expect(remainingAmount).toBe(0.5);
});
});
BigNumber는 대부분의 블록체인 개발 라이브러리에서 지원하며,
특히 Ethereum 개발에서 web3.js 라이브러리는 BigNumber를 사용할 수 있도록 메서드를 제공하고 있다.
각 대상이 되는 값을 BigNumber로 변환한 뒤
차액을 계산할 경우 부동 소수점연산의 오차를 방지할 수 있다.
테스트코드의 중요성
- 부동소수연산처리문제는 javascript의 문제라기보다는 모든 프로그래밍 언어에서 발생되기에 컴퓨터로 사고하는 것을 잊어서는 안 된다.
- UI상 클라이언트에 필요한 데이터표현으로 자릿수를 줄여야 한다면, 데이터무결성을 위해 정책상 필요한 숫자데이터와 Validation용 데이터 두 가지를 같이 내려주는 게 좋을 것 같다.
- 산술연산처리의 유닛테스트는 과해도 부족함이 없어 보인다.
'블록체인' 카테고리의 다른 글
[DID] DID개발을 위한 DID, DID Document 개념정리 (0) | 2023.09.26 |
---|---|
이더리움 토큰 스왑(Token Transfers)로그 확인 삽질기 (0) | 2023.08.19 |