SlideShare a Scribd company logo
1 of 13
浮動小數點
못믿을 그대
발단
• 게임코디 게시글…… 일이 없어 놀면서 이 글을 왜 봤던가….
도전
• 요상한 코드라 요상한 코드로 만들어봄.
• 요로코롬 짰음… 애초에 질문이 c#이라….
예상
• 앞서 코드를 눈으로 보면 대충 값이 나옴.
• C1은 13…
• C2도 13……
• 당연 C3도 13………..
암 절대 틀릴 리 없지!! 내말은 진리라오!!
결과
• 두둥… 실행해 보니… 결과는 내 얼굴을 후려침.
그리고 내 발가락도 가져감……
으 아니 컴파일러 양반.. 이러면 안되잖아!!
분석-1
• 갑자기 궁금했더랬지…아 왜 팠을까 그냥 묻을걸…
• 요게 만들어진 어셈 코드….
(봐도 뭔지 모르겠음..)
• 하나씩 파보자…
분석-2
• 처음엔 연산을 의심.
• 값이 엉뚱한 녀석은 다음 연산.
int c1 = (int)(a * b);
002026A5 fld dword ptr [ebp-40h]
002026A8 fmul dword ptr [ebp-44h]
002026AB fstp qword ptr [ebp-7Ch]
002026AE movsd xmm0,mmword ptr [ebp-7Ch]
002026B3 cvttsd2si eax,xmm0
002026B7 mov dword ptr [ebp-4Ch],eax
• 평범하게 FPU에 갔다 나오는 연산만 수행함.
• 특이점이라면 cvttsd2si 라는 SSE 명령어 셋을 쓴다 정도???
분석-3
• 정상인 연산은 다음.
int c3 = (int)(float)(a * b);
002526CC fld dword ptr [ebp-40h]
002526CF fmul dword ptr [ebp-44h]
002526D2 fstp dword ptr [ebp-74h]
002526D5 fld dword ptr [ebp-74h]
002526D8 fstp qword ptr [ebp-7Ch]
002526DB fld qword ptr [ebp-7Ch]
002526DE fstp qword ptr [ebp-7Ch]
002526E1 movsd xmm0,mmword ptr [ebp-7Ch]
002526E6 cvttsd2si eax,xmm0
002526EA mov dword ptr [ebp-54h],eax
• 역시 FPU를 좀더 여러 번 왕래한 것 뿐.. 연산 구조는 앞의 문제
와 동일.
분석-4
• 특이점 발견.
int c3 = (int)(float)(a * b);
002526CC 링 dword ptr [ebp-40h]
002526CF fmul dword ptr [ebp-44h]
002526D2 fstp dword ptr [ebp-74h] ->
002526D5 fld dword ptr [ebp-74h]
002526D8 fstp qword ptr [ebp-7Ch] ->
002526DB fld qword ptr [ebp-7Ch]
002526DE fstp qword ptr [ebp-7Ch]
002526E1 movsd xmm0,mmword ptr [ebp-7Ch]
002526E6 cvttsd2si eax,xmm0
002526EA mov dword ptr [ebp-54h],eax
• 값을 임의의 위치에 쓰고 다시 받으니 보정이 되어있네??? 이 부분은
(float) casting 부분임.
• 이 부분은 FPU 레지스터가 80비트이고 dword는 32비트 이므로 단정도가 잘리게 됨. 그래서
보정이 되는 거.
분석-5
• 근데 이것도 특이점일 뿐.. 원인은 아님.
• 뒤져보다 보니.. 다음 코드가 눈에 띄임.
00252695 mov dword ptr [ebp-44h], 3FA66666h
요놈… 0x3FA66666h
2진수로는 111111101001100110011001100110
10진수로는 1067869798
부동소수점으로는 1.29999995e+0000
• 아 뭔가 비슷하다. 이게 문제의 원인 같음.
분석-6
• 컴파일러가 코드를 생성할 때 코드에 상수가 있으면 이를 해당
generic 타입으로 생성해줌.
이 경우는 float이니 4바이트로 생성.. DWORD 타입.
근데 0.3은 표현할 수 없어서.. 0110이 반복되는 수로 표현.(정확히는 내부에서
정수 / 10^(n)로 계산해서 그럼..)
이런 수식을 확인할 수 있는 예로 다음과 같은 코드를 쓰면
float b = (float)13 * 0.1f;
0x3FA66667h로 들어감.
• 이게 바로 4바이트 변수로 복사되서 생기는 문제. 애초에 값의 변화
가 없다면 매번 동일한 결과를 볼 수 있겠지만 단정도의 손상이 발생
해서 12, 13으로 요상한 결과가 되는 거다.
분석-7
• 그럼 컴파일러 문제니 손 빨고 있어야 하나?
• 그건 아님. Intel에서 SSE 명령셋으로 새로운 걸 준비해서 제공했음.
• 기존 실수 연산에서 저런 오차가 자주 발생하자 FPU를 직접 사용하지 않고
새로운 명령어 셋으로 float연산을 SSE를 통해 assign하도록 변경함.(SSE 버퍼
는 128비트.)
• 해당 명령은 movss, mulss. (자세한 설명은 생락한다..)
• 이게 뭐냐 하면.. 모든 float값은 xmmX 메모리로 갔다가 오기(sse 전
용 register) 때문에 값이 잘리거나 변형이 없어짐.(128비트에서 32비
트로 복사시 잘라서 32비트만 가져오기 떄문에 단정도 손상이 없음.)
• 그래서 초기화 값이 길든 짧든 2의 배수이므로 문제없이 복사가 이
루어짐. 무의미한 변환이 없어져서 씽크가 맞음.
결론
• 모든 역사는 컴파일러에서..(퍽!)
• movss / mulss 를 쓰면 된다..(근데 어떻게 쓰라고..--;;)
• 쓰는 방법은 간단함. C++의 경우엔 VC2010부터.. GCC는 모르겠음.
• C#은… x86 컴파일러는 지원 안하고 x64는 자동으로 빌드해줌.
FLOAT은 거지같다…그냥 쓰지말자

More Related Content

Viewers also liked

Safety Meeting Starters (SMS) April 2013
Safety Meeting Starters (SMS) April 2013Safety Meeting Starters (SMS) April 2013
Safety Meeting Starters (SMS) April 2013safestrat
 
Project-Based Learning (PBL) Proposal [UIIT assessment item one]
Project-Based Learning (PBL) Proposal [UIIT assessment item one]Project-Based Learning (PBL) Proposal [UIIT assessment item one]
Project-Based Learning (PBL) Proposal [UIIT assessment item one]sycindyng
 
Peritaje en la construcción de proyectos inmobiliarios 1
Peritaje en la construcción de proyectos inmobiliarios 1Peritaje en la construcción de proyectos inmobiliarios 1
Peritaje en la construcción de proyectos inmobiliarios 1Magaly Caba
 
Towards an effective structural budget balance for economic stability
Towards an effective structural budget balance for economic stabilityTowards an effective structural budget balance for economic stability
Towards an effective structural budget balance for economic stabilityInvestigador Principal (IELAT_UAH)
 
Ns umass 2012 financialization an d measuring the labor share
Ns umass 2012 financialization an d measuring the labor shareNs umass 2012 financialization an d measuring the labor share
Ns umass 2012 financialization an d measuring the labor shareBert Mustafa
 
My city...god's city_how_to
My city...god's city_how_toMy city...god's city_how_to
My city...god's city_how_toRoger Hernandez
 
Remote Location Printing With OM Plus i-Sat
Remote Location Printing With OM Plus i-SatRemote Location Printing With OM Plus i-Sat
Remote Location Printing With OM Plus i-SatPlus Technologies
 
WordCamp Tokyo2012 Session
WordCamp Tokyo2012 SessionWordCamp Tokyo2012 Session
WordCamp Tokyo2012 Sessionregret raym
 
Harnessing e-Form Print Control
Harnessing e-Form Print ControlHarnessing e-Form Print Control
Harnessing e-Form Print ControlPlus Technologies
 
Ok. rude hand gestures of the world
Ok. rude hand gestures of the worldOk. rude hand gestures of the world
Ok. rude hand gestures of the worldGede Saputra
 
Abim ipd studies draft 1 (final version)
Abim ipd studies draft 1 (final version)Abim ipd studies draft 1 (final version)
Abim ipd studies draft 1 (final version)Tae wook kang
 

Viewers also liked (16)

Safety Meeting Starters (SMS) April 2013
Safety Meeting Starters (SMS) April 2013Safety Meeting Starters (SMS) April 2013
Safety Meeting Starters (SMS) April 2013
 
Fashion people for brands
Fashion people for brandsFashion people for brands
Fashion people for brands
 
Project-Based Learning (PBL) Proposal [UIIT assessment item one]
Project-Based Learning (PBL) Proposal [UIIT assessment item one]Project-Based Learning (PBL) Proposal [UIIT assessment item one]
Project-Based Learning (PBL) Proposal [UIIT assessment item one]
 
Hinduism
HinduismHinduism
Hinduism
 
Peritaje en la construcción de proyectos inmobiliarios 1
Peritaje en la construcción de proyectos inmobiliarios 1Peritaje en la construcción de proyectos inmobiliarios 1
Peritaje en la construcción de proyectos inmobiliarios 1
 
Branding
Branding Branding
Branding
 
UKTI : Matter Of Form - Think local, Act Global - Anant Sharma (w:notes)
UKTI : Matter Of Form - Think local, Act Global - Anant Sharma (w:notes)UKTI : Matter Of Form - Think local, Act Global - Anant Sharma (w:notes)
UKTI : Matter Of Form - Think local, Act Global - Anant Sharma (w:notes)
 
Towards an effective structural budget balance for economic stability
Towards an effective structural budget balance for economic stabilityTowards an effective structural budget balance for economic stability
Towards an effective structural budget balance for economic stability
 
Ns umass 2012 financialization an d measuring the labor share
Ns umass 2012 financialization an d measuring the labor shareNs umass 2012 financialization an d measuring the labor share
Ns umass 2012 financialization an d measuring the labor share
 
My city...god's city_how_to
My city...god's city_how_toMy city...god's city_how_to
My city...god's city_how_to
 
Remote Location Printing With OM Plus i-Sat
Remote Location Printing With OM Plus i-SatRemote Location Printing With OM Plus i-Sat
Remote Location Printing With OM Plus i-Sat
 
WordCamp Tokyo2012 Session
WordCamp Tokyo2012 SessionWordCamp Tokyo2012 Session
WordCamp Tokyo2012 Session
 
Bag drawing
Bag drawingBag drawing
Bag drawing
 
Harnessing e-Form Print Control
Harnessing e-Form Print ControlHarnessing e-Form Print Control
Harnessing e-Form Print Control
 
Ok. rude hand gestures of the world
Ok. rude hand gestures of the worldOk. rude hand gestures of the world
Ok. rude hand gestures of the world
 
Abim ipd studies draft 1 (final version)
Abim ipd studies draft 1 (final version)Abim ipd studies draft 1 (final version)
Abim ipd studies draft 1 (final version)
 

부동소수점 문제

  • 2. 발단 • 게임코디 게시글…… 일이 없어 놀면서 이 글을 왜 봤던가….
  • 3. 도전 • 요상한 코드라 요상한 코드로 만들어봄. • 요로코롬 짰음… 애초에 질문이 c#이라….
  • 4. 예상 • 앞서 코드를 눈으로 보면 대충 값이 나옴. • C1은 13… • C2도 13…… • 당연 C3도 13……….. 암 절대 틀릴 리 없지!! 내말은 진리라오!!
  • 5. 결과 • 두둥… 실행해 보니… 결과는 내 얼굴을 후려침. 그리고 내 발가락도 가져감…… 으 아니 컴파일러 양반.. 이러면 안되잖아!!
  • 6. 분석-1 • 갑자기 궁금했더랬지…아 왜 팠을까 그냥 묻을걸… • 요게 만들어진 어셈 코드…. (봐도 뭔지 모르겠음..) • 하나씩 파보자…
  • 7. 분석-2 • 처음엔 연산을 의심. • 값이 엉뚱한 녀석은 다음 연산. int c1 = (int)(a * b); 002026A5 fld dword ptr [ebp-40h] 002026A8 fmul dword ptr [ebp-44h] 002026AB fstp qword ptr [ebp-7Ch] 002026AE movsd xmm0,mmword ptr [ebp-7Ch] 002026B3 cvttsd2si eax,xmm0 002026B7 mov dword ptr [ebp-4Ch],eax • 평범하게 FPU에 갔다 나오는 연산만 수행함. • 특이점이라면 cvttsd2si 라는 SSE 명령어 셋을 쓴다 정도???
  • 8. 분석-3 • 정상인 연산은 다음. int c3 = (int)(float)(a * b); 002526CC fld dword ptr [ebp-40h] 002526CF fmul dword ptr [ebp-44h] 002526D2 fstp dword ptr [ebp-74h] 002526D5 fld dword ptr [ebp-74h] 002526D8 fstp qword ptr [ebp-7Ch] 002526DB fld qword ptr [ebp-7Ch] 002526DE fstp qword ptr [ebp-7Ch] 002526E1 movsd xmm0,mmword ptr [ebp-7Ch] 002526E6 cvttsd2si eax,xmm0 002526EA mov dword ptr [ebp-54h],eax • 역시 FPU를 좀더 여러 번 왕래한 것 뿐.. 연산 구조는 앞의 문제 와 동일.
  • 9. 분석-4 • 특이점 발견. int c3 = (int)(float)(a * b); 002526CC 링 dword ptr [ebp-40h] 002526CF fmul dword ptr [ebp-44h] 002526D2 fstp dword ptr [ebp-74h] -> 002526D5 fld dword ptr [ebp-74h] 002526D8 fstp qword ptr [ebp-7Ch] -> 002526DB fld qword ptr [ebp-7Ch] 002526DE fstp qword ptr [ebp-7Ch] 002526E1 movsd xmm0,mmword ptr [ebp-7Ch] 002526E6 cvttsd2si eax,xmm0 002526EA mov dword ptr [ebp-54h],eax • 값을 임의의 위치에 쓰고 다시 받으니 보정이 되어있네??? 이 부분은 (float) casting 부분임. • 이 부분은 FPU 레지스터가 80비트이고 dword는 32비트 이므로 단정도가 잘리게 됨. 그래서 보정이 되는 거.
  • 10. 분석-5 • 근데 이것도 특이점일 뿐.. 원인은 아님. • 뒤져보다 보니.. 다음 코드가 눈에 띄임. 00252695 mov dword ptr [ebp-44h], 3FA66666h 요놈… 0x3FA66666h 2진수로는 111111101001100110011001100110 10진수로는 1067869798 부동소수점으로는 1.29999995e+0000 • 아 뭔가 비슷하다. 이게 문제의 원인 같음.
  • 11. 분석-6 • 컴파일러가 코드를 생성할 때 코드에 상수가 있으면 이를 해당 generic 타입으로 생성해줌. 이 경우는 float이니 4바이트로 생성.. DWORD 타입. 근데 0.3은 표현할 수 없어서.. 0110이 반복되는 수로 표현.(정확히는 내부에서 정수 / 10^(n)로 계산해서 그럼..) 이런 수식을 확인할 수 있는 예로 다음과 같은 코드를 쓰면 float b = (float)13 * 0.1f; 0x3FA66667h로 들어감. • 이게 바로 4바이트 변수로 복사되서 생기는 문제. 애초에 값의 변화 가 없다면 매번 동일한 결과를 볼 수 있겠지만 단정도의 손상이 발생 해서 12, 13으로 요상한 결과가 되는 거다.
  • 12. 분석-7 • 그럼 컴파일러 문제니 손 빨고 있어야 하나? • 그건 아님. Intel에서 SSE 명령셋으로 새로운 걸 준비해서 제공했음. • 기존 실수 연산에서 저런 오차가 자주 발생하자 FPU를 직접 사용하지 않고 새로운 명령어 셋으로 float연산을 SSE를 통해 assign하도록 변경함.(SSE 버퍼 는 128비트.) • 해당 명령은 movss, mulss. (자세한 설명은 생락한다..) • 이게 뭐냐 하면.. 모든 float값은 xmmX 메모리로 갔다가 오기(sse 전 용 register) 때문에 값이 잘리거나 변형이 없어짐.(128비트에서 32비 트로 복사시 잘라서 32비트만 가져오기 떄문에 단정도 손상이 없음.) • 그래서 초기화 값이 길든 짧든 2의 배수이므로 문제없이 복사가 이 루어짐. 무의미한 변환이 없어져서 씽크가 맞음.
  • 13. 결론 • 모든 역사는 컴파일러에서..(퍽!) • movss / mulss 를 쓰면 된다..(근데 어떻게 쓰라고..--;;) • 쓰는 방법은 간단함. C++의 경우엔 VC2010부터.. GCC는 모르겠음. • C#은… x86 컴파일러는 지원 안하고 x64는 자동으로 빌드해줌. FLOAT은 거지같다…그냥 쓰지말자