Decimal calculation in Javascript

웹 개발/Problems 2024. 1. 16. 02:10

자바스크립트를 이용해 실수의 연산을 하다보면 소수점이 이상하게 나타나는 경우가 있다. 컴퓨터는 기본적으로 이진수를 이용하기 때문에 실수를 다루는 방식은 컴퓨팅 언어마다 다르다. Javascript는 모든 숫자를 IEEE 754 표준을 따르는 배정밀도 64 비트 부동 소수점 형식으로 표현하며, 이 형식은 실수를 근사치로 저장한다.

따라서 0.6 / 0.2 와 같은 연산을 실행 해보면 3이 아닌 2.999999999996 와 같은 예측에서 벗어난 값이 나온다. 이를 해결하기 위해 실수를 정수로 바꾼 후에 연산을 하고 다시 원래 실수로 돌려놓는 방법을 사용한다.

function findMostDecimal(array: number[]): number {
    let maxDecimal = 0;
    let numberWithMostDecimals = array[0];

    for (let num of array) {
        let decimalCount = countDecimalPlaces(num);
        if (decimalCount > maxDecimal) {
            maxDecimal = decimalCount;
            numberWithMostDecimals = num;
        }
    }

    return numberWithMostDecimals;
}

먼저 실수들 중에서 가장 소수점 자리가 큰 실수를 알아낸다.

export function countDecimalPlaces_10(value: number): number {
    if (!isFinite(value)) return 0; //무한대나 NaN인 경우, 0을 반환
    let text = value.toString();
    let index = text.indexOf('.');
    if (index === -1) return 1; //소수점이 없는 경우, 1을 반환. (정수이므로)
    let decimalPart = text.substring(index + 1);
    return Math.pow(10, decimalPart.length);
}

실수를 정수로 바꾸기 위해 지수를 구한다.

 

export function operateDecimals(
    value1: number,
    value2: number,
    operation: Tadjuster_method,
) {
    const mostDecimal = findMostDecimal([value1, value2]);
    const factor = countDecimalPlaces_10(mostDecimal);
    const newValue1 = Math.floor(value1 * factor);
    const newValue2 = Math.floor(value2 * factor);
    let result;
    switch (operation) {
        case 'add':
            result = (newValue1 + newValue2) / factor;
            break;
        case 'subtract':
            result = (newValue1 - newValue2) / factor;
            break;
        case 'multiply':
            result = (newValue1 * newValue2) / (factor * factor);
            break;
        case 'divide':
            result = newValue1 / newValue2; // 나눗셈의 경우, factor로 나눌 필요 없음
            break;
        default:
            throw new Error('Invalid operation');
    }
    return result;
}

이렇게 정수로 바꾼다음 연산을 진행한 뒤 지수를 다시 나눠주면 원하는 값을 구할 수 있다.

: