프로젝트 진행 중 생각지도 못했던 심각한 문제가 발생했다.
장바구니에 담은 음식의 칼로리를 소수점 단위로 조절하는 부분에서
이런 충격적인 일이 발생했다. 0.5,,, 0.4,,, 0.3....????
결론부터 말하자면 0.1 + 0.2 != 0.3
이라고 한다.
Javascript에서는 부동소수점 방식으로 실수를 표현한다. 이게 무슨 말이냐면 정수가 아닌 실수를 나타낼 때 이진법을 사용하므로 모든 숫자를 정확히 나타낼 수 없고, 그 실수에 가장 근사한 2진법의 수로 나타내기 때문에 나타나는 문제이다.
이런 이유 때문에 위의 결과가 나오게 된다고 한다. 조금 더 기술적으로 접근한다면 이러한 이유가 있다고 한다. 단순하게 0.1이나 0.2, 0.3을 할당해준다면 문제가 없겠지만 각각의 수를 더할 때 발생하는 문제였다.
알고보니 알사람은 다 아는 기본적인 프로그래밍 언어의 문제라고 한다.....
https://0.30000000000000004.com/ 충격적이게도 이런 사이트도 존재했다...........
사이트를 들어가보면 해당 문제가 발생하는 언어를 정리해 놓았다.
소수점의 자리수를 제한하는
toFixed()
함수를 사용했다.
// 갯수 카운팅하기!
const [count, setCount] = useState(props.amount);
const upCount = () => {
if (count >= 0.5) {
setCount(count + 0.5);
!editChk
? dispatch(setUpAmount(props.foodId))
: dispatch(editUpAmount(props.foodId));
} else {
setCount((count + 0.1).toFixed(1));
!editChk
? dispatch(setUpAmount(props.foodId))
: dispatch(editUpAmount(props.foodId));
}
};
카운팅한 값을
.toFixed(1)
함수를 통해 카운팅 결과값을 소수 1째자리 까지만 제한하였다.
바로
0.5 -> 0.4 -> 0.3 -> 0.2
-0.1
연산은 문제없이 계산되었는데
0.2 -> 0.2
+0.1
연산은 계산되지 않았다.
원인을 찾기위해 console을 찍어보니...
바로,, toFixed()
는 String을 반환하는 함수 였다.
원인은 자바스크립트에서
+
는-
나*
와 달리 문자열을 연결해 붙이는 기능을 가지고 있기 때문이었다.
바로 이렇게 문자열이 섞인 연산에서 +
는 -
와 다른 역할을 수행한다.
// 갯수 카운팅하기!
const [count, setCount] = useState(props.amount);
const upCount = () => {
if (count >= 0.5) {
setCount(count + 0.5);
!editChk
? dispatch(setUpAmount(props.foodId))
: dispatch(editUpAmount(props.foodId));
} else {
setCount(Number((count + 0.1).toFixed(1)));
!editChk
? dispatch(setUpAmount(props.foodId))
: dispatch(editUpAmount(props.foodId));
}
};
이렇게
toFixed()
를 통해 반환된 String 결과값을Number()
함수를 통해 숫자로 바꿔어주었다.