일반 부동소수점 (floating-point)

황제낙엽 2018.03.26 18:00 조회 수 : 1122

sitelink1 http://ponyozzang.tistory.com/60 
sitelink2 http://gafani.tistory.com/entry/Javascri...8%EA%B8%B0 
sitelink3  
sitelink4  
extra_vars4  
extra_vars5  
extra_vars6  

・부동소수점

  부동소수점으로 작성된 값을 부동소수점 리터럴이라고 부릅니다. 이번에는 부동소수점 리터럴을 스크립트 안에서 작성하는 방법을 확인해보겠습니다.

  소수점 형식의 경우는 정수 부분과 소수점 부분을 마침표를 사용해 구분해서 작성합니다.

 
3.14
0.0014

 

  그리고 지수 형식의 경우에는 기수가 10으로써 다음과 같이 작성할 수 있습니다.

 
3.2e2
2.4e-3

 

 [3.2e2]은 [3.2 x 10 2]으로 [320.0]입니다. 그리고 [2.4e-3]은 [2.4 x 10 -3]으로 [0.0024]입니다.

 그리고 [e] 대신에 [E]를 사용해도 괜찮습니다.

 
3.2E2
2.4E-3

 

 

 

 

 

[Javascript] 소수점 자리수 처리하기

소수점 8자리 수끼리 합산을 했는데, 소수점 14자리가 나왔습니다.

모든 수가 그런것이 아니라, 어느 시점에서 그렇게 변하였는데, 간단히 예제를 보자면:

35.27387426 "+" 1.79806217 "=" 37.07193643
37.07193643 "+" 12.00537839 "=" 49.07731482
49.07731482 "+" 0.66331486 "=" 49.74062968
49.74062968 "+" 9.04520268 "=" 58.78583236
58.78583236 "+" 1.20602704 "=" 59.9918594
59.9918594 "+" 1.20602702 "=" 61.19788642
61.19788642 "+" 0.60301351 "=" 61.80089993
61.80089993 "+" 2.14995101 "=" 63.95085094
63.95085094 "+" 1.18407028 "=" 65.13492122
65.13492122 "+" 1.18407028 "=" 66.3189915
66.3189915 "+" 13.83537715 "=" 80.15436865
80.15436865 "+" 0.59203514 "=" 80.74640378999999
80.74640379 "+" 9.85853479 "=" 90.60493858000001
90.60493858 "+" 9.39506142 "=" 100

위에서 보면 아래쪽 부분에서 부터 8자리끼리 합산하게 되면 소수점이 변경되게 되는데요. 이것은 버그가 아닙니다. 일반적으로 알려진 이슈인데요. 실수 값을 계산할 때 고정된 정밀도를 가지고 계산하기 때문입니다.

그러니까 왜?

자세히 설명하자면, IEEE 754 표준 2진 부동 소수점을 계산하는 모든 프로그래밍 언어들에게서 나타나는 이슈인데요. 자바스크립트는 64-bits 부동 소수점 표현법을 사용하는데, 이것은 Java의 double 과 같아요. 이 문제의 요점은 숫자가 2의 제곱으로 표현된다는 부분에 있어요. 분모가 2의 제곱이 아닌 유리수 (0.1 1/10과 같은)는 정확하게 표현이 될 수 없기 때문예요.

0.1 을 표준 binary64 형식으로 다음과 같이 정확하게 표현할 수 있어요.

  • 10진법으로 0.1000000000000000055511151231257827021181583404541015625
  • C99 hexfloat notation 으로 0x1.999999999999ap-4

반대로, 유리수 0.1 과 동일한 1/10 은 다음과 같이 정확히 표현할 수 있어요.

  • 10진법으로 0.1
  • C99 hexfloat noation 으로 0x1.99999999999999...p-4

이 설명을 쉽게 이해하려면, 다음과 같은 코드를 보시면 이해가 되실 거예요.

> 0.1 + 0.2 == 0.3
< false
> 0.1 + 0.2 === 0.3
< false

이해가 잘 안가신다구요? 그럼 다음의 예제를 보시면 좀 더 이해하기 쉬우실 거예요.

> 1/10 + 2/10 == 3/10
< false
> 1/8 + 2/8 == 3/8
< true

그러면 이해하셨다고 하고, 해결법을 찾아보니 다음과 같이 간단하게 처리가 되었어요.

> 80.74640378999999.toFixed(8)
< "80.74640379"

Number.prototype.toFixed()

toFixed() 메서드는 고정 소수점 표현법을 사용하여 숫자 형식을 지정해요.

문법

numObj.toFixed([digits])

인자들

digits 부가적임. 숫자의 소수점을 표현하고 싶은 자리수. 0 ~ 20까지 가능하고요, 이 값을 비워놓으면 0으로 처리해요.

리턴값

고정 소수점으로 표현된 String을 줘요.

예외처리

RangeError digits 가 너무 크거나 작을 때.

TypeError 이 메서드를 호출한 객체가 Number의 객체가 아닐 때.

설명

toFixed() 는 지수 표기법을 사용하지 않고 소수점 뒤에 정확한 자리수를 가지는 숫자 객체의 문자열을 리턴해요. 필요한 경우에 숫자는 반올림이 되고, 소수 부분에는 필요에 따라서 0으로 채워져 지정된 길이가 되요. 숫자 객체가 1e + 21 보다 큰 경우에 이 메서드는 단순히 Number.prototype.toString() 을 호출하고 지수 표기법의 문자열을 리턴해요.

예제들

var numObj = 12345.6789;

numObj.toFixed();       // Returns '12346': 소수점 전체를 반올림
numObj.toFixed(1);      // Returns '12345.7': 반올림
numObj.toFixed(6);      // Returns '12345.678900': 모자란 부분은 0으로 채움
(1.23e+20).toFixed(2);  // Returns '123000000000000000000.00'
(1.23e-10).toFixed(2);  // Returns '0.00'
2.34.toFixed(1);        // Returns '2.3'
2.35.toFixed(1);        // Returns '2.4'. 이 경우에 반올림됨을 기억하세요.
-2.34.toFixed(1);       // Returns -2.3 (연산자 우선순위 때문에 음수 리터럴은 문자열을 리턴하지 않아요.)
(-2.34).toFixed(1);     // Returns '-2.3' (괄호를 사용하지 않는다면...)

참조


 

 

 

 

 

 

 

Floating-point cheat sheet for JavaScript

브라우저 개발자 콘솔에서 console.debug(0.1*0.2) 를 출력해보면 0.020000000000000004 라고 출력된다

이는 부동 소수점 연산 오류이다

기본 개념과 심화학습 그리고 해결방안은 다음의 사이트에서 학습 가능하다 -> http://floating-point-gui.de/languages/javascript/

일부 내용을 가져온다면 

 

Floating-point cheat sheet for JavaScript

Floating-Point Types

JavaScript is dynamically typed and will often convert implicitly between strings and floating-point numbers (which are IEEE 64 bit values). To force a variable to floating-point, use the global parseFloat() function.

	var num = parseFloat("3.5");

Decimal Types

The oldest decimal type for JavaScript seems to be a port of Java’s BigDecimal class, which also supports rounding modes:

	var a = new BigDecimal("0.01");
	var b = new BigDecimal("0.02");
	var c = a.add(b); // 0.03
	var d = c.setScale(1, BigDecimal.prototype.ROUND_HALF_UP);

There is also bignumber.js, which is smaller and faster:

	BigNumber.config({ROUNDING_MODE: BigNumber.ROUND_HALF_UP})
	var a = new BigNumber("0.01");
	var b = new BigNumber("0.02");
	var c = a.plus(b); // BigNumber(0.03)
	var d = c.toFixed(1); // "0.0"

How to Round

	var num = 5.123456;
	num.toPrecision(1) //returns 5 as string
	num.toPrecision(2) //returns 5.1 as string
	num.toPrecision(4) //returns 5.123 as string

Using a specific rounding mode:

	new BigDecimal("1.25").setScale(1, BigDecimal.prototype.ROUND_HALF_UP);

Resources

 

 

여기서 언급된 오픈소스의 javascript 라이브러리들이 있다

 

1. https://github.com/dtrebbien/BigDecimal.js

2. https://github.com/iriscouch/bigdecimal.js

3. https://github.com/MikeMcl/bignumber.js

4. https://github.com/MikeMcl/big.js

 

현재(2018.03.26) 기준 라이브러리 버전들은 첨부파일로 업로드해둔다

 

dtrebbien_BigDecimal.js-master_20180326.zip

iriscouch_bigdecimal.js-master_20180326.zip

mikemcl_big.js-master_20180326.zip

mikemcl_bignumber.js-master_20180326.zip

 

번호 제목 글쓴이 날짜 조회 수
197 경과 시간 구하기 황제낙엽 2019.10.04 1071
196 입력받은 날짜와 현재 날짜와의 비교 함수 황제낙엽 2019.08.02 499
195 사용자 모듈 만들기 황제낙엽 2019.07.09 41735
194 charcode 32와 160 차이 (javascript char 160 to 32) 황제낙엽 2019.05.11 55
193 UTF-8 한글 초성 추출 (자바스크립트) 황제낙엽 2019.05.07 243
192 IE브라우저에서 서버의 XML파일을 ajax로 가져와 DOM파싱하는 예제 (XMLHttpRequest, XML, ActiveXObject) 황제낙엽 2018.11.23 103
191 XMLHttpRequest.timeout 황제낙엽 2018.11.03 248
» 부동소수점 (floating-point) file 황제낙엽 2018.03.26 1122
189 User Agent Parser들 황제낙엽 2017.11.20 4132
188 window.postMessage 이해하기 file 황제낙엽 2017.10.16 1612
187 브라우저의 새로고침과 종료에 대한 이벤트 황제낙엽 2017.08.11 2725
186 XMLHttpRequest 제대로 활용하기 file 황제낙엽 2017.08.01 58
185 Ajax (XMLHttpRequest) 샘플 황제낙엽 2017.08.01 93
184 Javascript CORS/XSS 극복하는(피하는) 방법 file 황제낙엽 2017.07.31 648
183 JSON.parse() - feat. Object.assign 황제낙엽 2017.07.09 77
182 자바스크립트 타입 비교 테이블 + 테이블 작성 스크립트 [1] file 황제낙엽 2017.06.23 85
181 HTTP 접근 제어 (CORS) 황제낙엽 2017.05.29 125
180 |= 비트 OR 대입 연산자 (복합대입연산자) 황제낙엽 2017.03.15 73
179 CORS(Cross-Origin Resource Sharing) - 5 file 황제낙엽 2017.03.07 261
178 CORS(Cross-Origin Resource Sharing) - 4 file 황제낙엽 2017.03.07 873