IEEE 754

From KBase

Jump to: navigation, search

[edit] A Talk about IEEE 754 (Floating Point Number)

[edit] Introduction

친구가 floating point 의 계산 오류에 대해 물어보길래 나름 http://en.wikipedia.org/ 등을 찾아 가면서 대답을 했다. 공유해 보는 것도 좋을 것 같아 친구의 허락을 얻어 올린다.

[edit] Talk

hi
하이
I wanna ask you some odd thing (in my opinion)
자바에서 0.1+0.7=0.8 이 아니다..
이게 먼소리냐
글쎄다
0.799999999 라는데
그렇담 0.1 이 0.999999 였겠지..라고 하니까
아니래 --;
그럴 수 있어.
C 나 Java 에서 "실수" 는
floating point
라고 해서
부동 소수점
IEEE 몇번이더라
여튼 거기서 제안한 방식을 따르거든
흠...실수가 실수가 아니란거냐
실수이긴 한데
2진수라는게 문제지.
예를 들어
1/3 + 1/3 을 한다고 해봐
우리가 표현하는 10진수로는
소수점 4자리까지만 표현하기로 해봐
0.3333 + 0.3333
1/3이야 문제가 생기겠지
세 번 더하자
0.3333 + 0.3333 + 0.3333
그건 알겠다만 0.1+0.7은
은 0.9999 가 되잖아
1+7과 왜 많이 다르냐고
똑같아
10진수가
왜?
10 진수로 소수점 4자리는
1/3 을 정확하게 표현 못하고
근처에만 간거잖아
2 진수로도
그니까 0.1은..0.1000 이고 0.7000 이자나
0.1 을 제대로 표현 못해.
엥?
0.1 이란 개념은 10 진수에서 나온거잖아
0.1을 왜 표현못해
그렇지
2진수로 표현해 보면
0.1 은 10 진수로 0.5 지?

0.01 은 10진수로 0.25 구
0.001 은 0.125
0.0001 은 0.0625
이런 식이라면 10 진수로 0.1 이 되려면
2진수로는
잠만..
0.1은 10진수로 0.5
오케이
0.0001 보다 크고 0.001 보단 작은 수가 되어야 하거든
10진수 0.2가 안된다는거군
한번 해보자..
0.1 을 2진수로 표현해보니
0x3DCCCCCD 다.
음. 어차피 내가 저걸 해석할 능력이 안되는구나
머냐 --;
3DCCCCCD 10110011001100110011001110111100
MSB 부터 써야겠군.
3DCCCCCD 00111101110011001100110011001101
ㅋㅋㅋ 어지럽다
저 32 개의 0/1 중
일부는 지수 (exp)
이고
나머지는 유효숫자 야
http://en.wikipedia.org/wiki/IEEE_754
맨앞에 0 이 sign
음..2진수가 문제군
뒤에 01111011 가 지수
10011001100110011001101
이게 fraction 이네

인제 어지러워 ㅎㅎ
지수는 10 진수로 하면
123 이고
스펙에 따라 127 을 빼면 -4
즉 -4 승이지.
다음, 뒤에 숫자를 붙여 보면
1.10011001100110011001101
여기 -4 승을 적용하면
0.000110011001100110011001101
아까 내가 0.0001 보다 큰 수일거라고 했잖아
그러네
여튼 뒤에 계속 되어야 할텐데
2진수로는 10진수 0.1 을 표현 못하는거지
음...소수의 역습이군
10 진수로 1/3 을 표현할 때 0.3 에 3 위에 점 찍듯이
0.000110011001100110011001101
얘도 반복되는 패턴이 보이긴 한다.

여튼 0.333 의 3배가 1 이 아닌 것과 동일한 이유로
0.1 + 0.7 이 0.8 이 안 될 가능성이 있는거지.
IEEE754 에서는 이럴 수 있는 가능성에 대해 언급하고 있고
정확한 계산을 위해서는 사용하지 말 것을 권장해
정확한 계산을 위해서는 사용하지 말것 ㅎㅎㅎㅎㅎ
다만 C 나 Java 에서의 float 라는 type 은
IEEE754 를 따른다고 되어 있으니까
알아서 써야지.
오케이...고맙
근데 누가 그랬어?
0.1 + 0.7 은 0.8 이라고 나오는데
우리 IT가
안나온다고 주장하길래
안나온다며
나와?
숫자에 따라서 정확할 수도 있고
틀릴 수도 있는데
대개는 맞거든
가끔 틀리는 경우가 있어
0.1 + 0.7 이 그 경우인지 모르겠어서
해봤는데
0.8 나오네.

Java 에선 안해봤고
C 랑 Perl 에서 해봤어

0.100000 3DCCCCCD 00111101110011001100110011001101
0.700000 3F333333 00111111001100110011001100110011
0.800000 3F4CCCCD 00111111010011001100110011001101

나보고 알아먹으라고 보낸거 아니지 ㅎㅎㅎ
몇 개 해봤는데

$ ./a.exe 32.1 0.7
32.099998 42006666 01000010000000000110011001100110
 0.700000 3F333333 00111111001100110011001100110011
32.799999 42033333 01000010000000110011001100110011

32.1 을 제대로 표현 못하네.

$ ./a.exe 13.1 30.7
13.100000 4151999A 01000001010100011001100110011010
30.700001 41F5999A 01000001111101011001100110011010
43.800003 422F3334 01000010001011110011001100110100

둘다 를텼는데 답은 맞는 경우

$ ./a.exe 23.3 30.7
23.299999 41BA6666 01000001101110100110011001100110
30.700001 41F5999A 01000001111101011001100110011010
54.000000 42580000 01000010010110000000000000000000


./a.exe 12345.3 1234.7
12345.299805 4640E533 01000110010000001110010100110011
 1234.699951 449A5666 01000100100110100101011001100110
13580.000000 46543000 01000110010101000011000000000000

숫자가 커질수록 유효숫자가 모자라니까
오차는 나는데
합은 또 맞네.
여튼, 이런 특성이 있다. IEEE754 는.
흠..커질수록 맞다
그럼 큰수로 더한다음에 큰수 정수를 빼면?
 ?

./a.exe 12345.3 -1234.7
12345.299805 4640E533 01000110010000001110010100110011
-1234.699951 C49A5666 11000100100110100101011001100110
11110.599609 462D9A66 01000110001011011001101001100110

모 개판이네.
개판일거까지야
http://docs.sun.com/source/806-3568/ncg_goldberg.html
이런 글이 있는 거 보면
(모 읽고 싶진 않다만 ^^)
여튼, 그래서 float 는 부호 sign 1, exp 8, fraction 23 비트를 쓰는 애고
(총 32비트)
double 은 64 비트를 써.
double을 추천한다는거냐
아니
fraction 길이가 늘어난다고 해서
계산이 정확해 지는건 아니지

Personal tools
Wiki Help (mediawiki.org)