작콩큰콩
[자바스크립트 JavaScript] 소수점 계산 오류 본문
자바스크립트로 소수점을 계산한 경우
아주 놀랍게도 00000000004를 볼 수 있다. 즉 더하기가 잘 안 된다는 소리 더하기도 안 되는데 곱하기 하면 난리 날 것이다.
parseFloat 같은 거 쓴다고 되는게 아니라고 하셨다.
let a = 0.1;
let b = 0.2;
console.log(parseFloat(a) + parseFloat(b)); // 0.30000000000000004
원인
컴퓨터는 0과 1로만 이루어져서 우리가 사용하는 10진법과는 다르게 컴퓨터는 2진법을 사용해 계산을 한다.
몇몇 소수의 경우에는 10진법을 2진법으로 변환할 때 무한소수가 되어버리는데, 유한한 컴퓨터의 자원을 활용하는 프로그램은 당연히 저장공간의 한계로
인해 결국 무한 소수를 유한한 수로 바꾸게 되고, 그 과정에서 나타나는 미세한 오차가 계산의 오류를 범하게 하는 것이라고 한다. 그래서 어느 순간에 값을 자른 것 같다.
- 더 상세한 내용 - 인용해 왔는데 좀 더 공부해야 할 것 같다.
- 근본을 따지자면 사실 숫자는 내부적으로 64비트 형식 IEEE-754으로 표현되기 때문에 숫자를 저장하려면 정확히 64비트가 필요하다. 64비트 중 52비트는 숫자를 저장하는 데 사용되고, 11비트는 소수점 위치를(정수는 0), 1비트는 부호를 저장하는 데 사용된다. 그런데 너무 큰 수는 표현하는 데 64비트를 초과하기 때문에 Infinity로 처리 된다.
해결 방안
- 박이사님께서 알려주신 방법
1.SQL단에서 계산해서 가져오기
- SQL 에서는 계산하지 않고 java 단에서 BigDecimal 로 계산해서 가져오기
- 공식문서에선 BigDecimal을 불변의 성질을 띠며, 임의 정밀도와 부호를 지니는 10진수라고 표현합니다.
- 아래 활용하는 코드
import java.math.BigDecimal;
public class study {
public static void number() {
BigDecimal a = new BigDecimal(0.1);
System.out.println(a);
BigDecimal b = new BigDecimal("0.1");
System.out.println(b);
BigDecimal c = new BigDecimal("0.2");
System.out.println(c);
System.out.println("\n" +"사칙연산");
System.out.println(b.add(c));
System.out.println(b.subtract(c));
System.out.println(b.multiply(c));
System.out.println(b.divide(c));
// 주목할 부분은 나눗셈입니다.
// 기본적으로 BigDecimal은 소수점 처리(rounding)을 하지 않고 정확한 몫을 반환합니다.
// 만약 1 나누기 3처럼 몫의 값이 무한소수인 경우(Non-terminating decimal expansion)엔 ArithmeticException이 발생합니다.
System.out.println("");
System.out.println(BigDecimal.valueOf(1.12));
};
public static void main(String[] args) {
number();
}
}
3. javascript 라이브러리(Math.js) 등을 이용하여 계산하기
이 방법은 모르겠네… 이런 상태인데??
- Math.floor() : 괄호 안의 숫자를 내림
- Math.ceil() : 괄호 안의 숫자를 올림
- Math.round() : 괄호 안의 숫자를 반올림
- Math.abs() : 괄호 안의 숫자의 절대값
- Math.sqrt() : 괄호 안의 숫자의 루트 값(제곱근)
- Math.pow() : 괄호 안의 첫 번째 숫자가 밑, 두 번째 숫자가 지수(거듭제곱)
- Math.random() : 0이상 1미만의 값 랜덤 리턴
conole.log(Math.floor(10.99)); // 10
conole.log(Math.ceil(99.1)); // 100
conole.log(Math.round(99.6)); // 100
conole.log(Math.abs(-50)); // 50
conole.log(Math.abs(50)); // 50
conole.log(Math.sqrt(2)); // 1.4142135623730951
4. post 를 이용하든 다른 방법으로 하든 java 단에서 BigDecimal로 계산해서 가져오기
- 2번과 동일한 상태이다.
5. 그 외
- 이사님께서 parseFloat(value).toFixed(4) 이렇게 했을 때 0.300000000000004 나왔는데 4자리 짤라서 쓰는건 찝찝하지 않는가? 라고 하셨다.
'작은 콩 개발자 > JS' 카테고리의 다른 글
js 에서 class 생성 (0) | 2023.07.10 |
---|---|
js에서 배열 생성 (array) (0) | 2023.07.10 |
[js] 에서 배열 다루기 (0) | 2023.06.22 |
[jsp][js] JSP내에서 Java변수 사용하기 / javascript 에서 java 변수 사용하기 (0) | 2023.06.22 |
[js] isNaN() 숫자인지 확인 (is not number) (0) | 2023.06.01 |
Comments