37
부부부부부 (FLP) 부부부부부부부 부부부

부동소수점 (FLP)

  • Upload
    prem

  • View
    112

  • Download
    1

Embed Size (px)

DESCRIPTION

부동소수점 (FLP). 사이버보안학과 김현성. 제안. FLP00-C 부동소수점 수의 제한을 이해하라 FLP01-C 부동소수점 표현식을 재배치할 때 주의하라 FLP02-C 정확한 계산이 필요할 때는 부동소수점 수를 배제할 수 있는지 고려하라 FLP03-C 부동소수점 에러를 발견하고 처리하라. 규칙. FLP30-C 부동소수점 변수를 루프 카운터로 사용하지 마라 FLP31-C 함수에 복소수를 사용하면서 실제 값을 얻을 거라 기대하지 마라 - PowerPoint PPT Presentation

Citation preview

Page 1: 부동소수점 (FLP)

부동소수점 (FLP)

사이버보안학과 김현성

Page 2: 부동소수점 (FLP)

2/37

제안 FLP00-C 부동소수점 수의 제한을 이해하라 FLP01-C 부동소수점 표현식을 재배치할 때 주의하라 FLP02-C 정확한 계산이 필요할 때는 부동소수점 수를 배제할

수 있는지 고려하라 FLP03-C 부동소수점 에러를 발견하고 처리하라

Page 3: 부동소수점 (FLP)

규칙

FLP30-C 부동소수점 변수를 루프 카운터로 사용하지 마라 FLP31-C 함수에 복소수를 사용하면서 실제 값을 얻을 거라

기대하지 마라 FLP32-C 수학 함수에서 도메인 에러나 영역 에러를 찾고

예방하라 FLP33-C 부동소수점 연산용 정수는 먼저 부동소수점으로

바꿔라 FLP34-C 부 동 소 수 점 변 환 이 새 로 운 타 입 의 범 위 안 에

들어가는지 확인하라

3/37

Page 4: 부동소수점 (FLP)

4/37

제안 FLP00-C 부동소수점 수의 제한을 이해하라 FLP01-C 부동소수점 표현식을 재배치할 때 주의하라 FLP02-C 정확한 계산이 필요할 때는 부동소수점 수를 배제할

수 있는지 고려하라 FLP03-C 부동소수점 에러를 발견하고 처리하라

Page 5: 부동소수점 (FLP)

5/37

부동소수점 수의 제한을 이해하라

부동소수점

실수를 부호 , 지수 , 소수의 세 부분으로 구분하여 표현

4 바이트를 사용하는 부동 소수점 형식

14e2123e-3

14x102=1400123x10-

3=0.123

Page 6: 부동소수점 (FLP)

부동소수점

6/37

부동소수점 수의 제한을 이해하라

어떤 시스템으로 구현되었든지 고정된 정밀도를 가짐

반올림과 관련된 에러 유발 가능성 있음 시스템에 따라 정밀도와 표현 가능한

값의 범위가 다름

=> 컴퓨터는 유한한 개수의 숫자 표현 가능

Page 7: 부동소수점 (FLP)

FLP00-C 코드 예

#include <stdio.h>

int main (void) {float f = 1.0f / 3.0f;printf(“Float is %.50f\n”, f);return 0;

}

7/37

=> 0.33333333333333333333333333

부동소수점 수의 제한을 이해하라

=> Linux GCC 0.33333334326744079843750000XP Visual C++ 9.0 0.33333334326744080000000000

Page 8: 부동소수점 (FLP)

8/37

제안 FLP00-C 부동소수점 수의 제한을 이해하라

FLP01-C 부동소수점 표현식을 재배치할 때 주의하라

FLP02-C 정확한 계산이 필요할 때는 부동소수점 수를 배제할 수 있는지 고려하라

FLP03-C 부동소수점 에러를 발견하고 처리하라

Page 9: 부동소수점 (FLP)

FLP01-C 코드 예double x, y, z;/* ... */x = (x * y) * z; z = (x – y) + y;z = x + x * y;y = x / 5.0;

9/37

=> 범위 한계 및 정밀도 한계로 인해서 문제 발생됨 (Round off)

부동소수점 표현식을 재배치할 때 주의하라

x *= y * z; z = x;z = x * (1.0 + y);y = x * 0.2;

Page 10: 부동소수점 (FLP)

10/37

제안 FLP00-C 부동소수점 수의 제한을 이해하라 FLP01-C 부동소수점 표현식을 재배치할 때 주의하라

FLP02-C 정 확 한 계 산 이 필 요 할 때 는 부동소수점 수를 배제할 수 있는지 고려하라

FLP03-C 부동소수점 에러를 발견하고 처리하라

Page 11: 부동소수점 (FLP)

FLP02-C 부적절한 코드 예#include <stdio.h>float mean(float array[], int size) {

float total = 0.0;int i;for (i=0; i<size; i++){

total += array[i];printf(“array[%d] = %f and total is %f\n”, i, array[i], total);

}if (size != 0) return total / size;else return 0.0;

}enum {array_size = 10};float array_value = 10.1;int main(void) {

float array[array_size];float avg;int i;for (i=0; i<array_size; i++) array[i] = array_value;avg = mean(array, array_size);printf(“mean is %f\n, avg);

11/37

=> mean is 10.1=> mean is 10.099999 64Linux with GCC 4.1

정확한 계산이 필요할 때는 부동소수점 수를 배제할 수 있는지 고려하라

if (avg == array[0]) { printf(“array[0] is the mean\n”); } else { printf(“array[0] is not the mean\n”); } return 0;}

Page 12: 부동소수점 (FLP)

12/37

정확한 계산이 필요할 때는 부동소수점 수를 배제할 수 있는지 고려하라FLP02-C 해결방법

#include <stdio.h>float mean(int array[], int size) { int total = 0; int i; for (i=0; i<size; i++){ total += array[i]; printf(“array[%d]=%f and total is %f\n”, i, array[i]/100.0, total/100.0); } if (size != 0) return total / size; else return 0.0;}enum {array_size = 10};int array_value = 1010;int main(void) { int array[array_size]; float avg; int i; for (i=0; i<array_size; i++) array[i] = array_value; avg = mean(array, array_size); printf(“mean is %f\n, avg/100.0);

if (avg == array[0]) { printf(“array[0] is the mean\n”); } else { printf(“array[0] is not the mean\n”); } return 0;}

Page 13: 부동소수점 (FLP)

13/37

제안 FLP00-C 부동소수점 수의 제한을 이해하라 FLP01-C 부동소수점 표현식을 재배치할 때 주의하라 FLP02-C 정확한 계산이 필요할 때는 부동소수점 수를 배제할

수 있는지 고려하라

FLP03-C 부 동 소 수 점 에 러 를 발 견 하 고 처리하라

Page 14: 부동소수점 (FLP)

FLP03-C 부적절한 코드 예void fpOper_noErrorChekin(void) {

/* ... */double a = 1e-40, b, c = 0.1;float x = 0, y;/* 부정확하며 언더플로우가 발생 */y = a;/* 0 으로 나누는 에러 */b = y / x;/* 부정확함 ( 정밀도를 잃어버림 ) */c = sin(30) * a;/* ... */

}

14/37

부동소수점 에러를 발견하고 처리하라

Page 15: 부동소수점 (FLP)

pragma

컴파일러에 직접 명령을 내리기 위한 지시자 ( #pragma STDC 로 시작 )

종류#pragma once : 해당명령 한번만 컴파일#pragma warning : 특정 경고 에러 띄우지 않음#pragma comment : 라이브러리를 인클루드할 때 많이 사용#pragma pack : 메모리 공간 최적화

15/37

부동소수점 에러를 발견하고 처리하라

Page 16: 부동소수점 (FLP)

fenv.h

부동소수점 환경을 제어하기 위한 C99표준함수

16/37

부동소수점 에러를 발견하고 처리하라

Function Description

feclearexcept

Clears exceptions

fegetenv Stores current floating point environment

fetestexcept Tests whether certain exceptions have been raised

Page 17: 부동소수점 (FLP)

FLP03-C 해결방법#include <fenv.h> /* 부동소수점 에러 처리 표준 함수 */#pragma STDC FENV_ACCESS ONvoid fpOper_fenv(void) {

double a = 1e-40, b, c = 0.1;float x = 0, y;int fpeRaised;/* ... */feclearexcept(FE_ALL_EXCEPT);/* a 를 y 에 저장하면 값이 부정확해지고 언더블로우 발생 */y = a;fpeRaised = fetestexcept(FE_ALL_EXCEPT);/* fpeRaised 는 FE_INEXACT 와 FE_UNDERFLOW 가짐 */feclearexcept(FE_ALL_EXCEPT);/* 0 으로 나누는 연산 */b = y / x;fpeRaised = fetestexcept(FE_ALL_EXCEPT);/* fpeRaised 는 FE_DIVBYZERO 가짐 */feclearexcept(FE_ALL_EXCEPT);c = sin(30) * a;fpeRaised = fetestexcept(FE_ALL_EXCEPT);/* fpeRaised 는 FE_INEXACT 가짐 */feclearexcept(FE_ALL_EXCEPT);/* ... */

}

17/37

부동소수점 에러를 발견하고 처리하라

Page 18: 부동소수점 (FLP)

규칙

FLP30-C 부동소수점 변수를 루프 카운터로 사용하지 마라

FLP31-C 함수에 복소수를 사용하면서 실제 값을 얻을 거라 기대하지 마라

FLP32-C 수학 함수에서 도메인 에러나 영역 에러를 찾고 예방하라

FLP33-C 부동소수점 연산용 정수는 먼저 부동소수점으로 바꿔라

FLP34-C 부 동 소 수 점 변 환 이 새 로 운 타 입 의 범 위 안 에 들어가는지 확인하라

18/37

Page 19: 부동소수점 (FLP)

FLP30-C 부적절한 코드 예

for(float x = 0.1f; x <= 1.0f; x+= 0.1f) {

/* ... */}

19/37

=> IA-32 머신 Window XP, Visual C++ 2005 v8.0 -> 9 회 실행

=> for 루프 10 회 실행

부동소수점 변수를 루프 카운터로 사용하지 마라

Page 20: 부동소수점 (FLP)

FLP30-C 해결방법

for(size_t i = 1; i <= 10; i += 1) {float x = i/10.0f;/* ... */

}

20/37

부동소수점 변수를 루프 카운터로 사용하지 마라

Page 21: 부동소수점 (FLP)

규칙

FLP30-C 부동소수점 변수를 루프 카운터로 사용하지 마라

FLP31-C 함수에 복소수를 사용하면서 실제 값을 얻을 거라 기대하지 마라

FLP32-C 수학 함수에서 도메인 에러나 영역 에러를 찾고 예방하라

FLP33-C 부동소수점 연산용 정수는 먼저 부동소수점으로 바꿔라

FLP34-C 부 동 소 수 점 변 환 이 새 로 운 타 입 의 범 위 안 에 들어가는지 확인하라

21/37

Page 22: 부동소수점 (FLP)

복소수로 호출하면 안되는 함수

atan2 cbrt ceil copysign erf erfc exp2

expm1

fdim floor fma fmax fmin fmod frexp hypot

ilogb ldexp lgamma llrint

llround

log10 log1p log2

logb lrint lround nearbyint

nextafter

nexttoward

remainder

remquo

rint round scalbnscalbln

tgamma trunc

22/37

함수에 복소수를 사용하면서 실제 값을 얻을 거라 기대하지 마라

Page 23: 부동소수점 (FLP)

FLP31-C 부적절한 코드 예

double complex c = 2.0 + 4.0 * I;/* ... */double complex result = log2(c);

23/37

함수에 복소수를 사용하면서 실제 값을 얻을 거라 기대하지 마라

=> log2 는 실수값 만을 허용하는 타입이므로정의되지 않은 동작 초래

Page 24: 부동소수점 (FLP)

FLP31-C 해결방법

double complex c = 2.0 + 4.0 * I;/* ... */double complex result = log2(creal(c));

24/37

함수에 복소수를 사용하면서 실제 값을 얻을 거라 기대하지 마라

복소수의 실수부 계산

Page 25: 부동소수점 (FLP)

규칙

FLP30-C 부동소수점 변수를 루프 카운터로 사용하지 마라 FLP31-C 함수에 복소수를 사용하면서 실제 값을 얻을 거라

기대하지 마라

FLP32-C 수학 함수에서 도메인 에러나 영역 에러를 찾고 예방하라

FLP33-C 부동소수점 연산용 정수는 먼저 부동소수점으로 바꿔라

FLP34-C 부 동 소 수 점 변 환 이 새 로 운 타 입 의 범 위 안 에 들어가는지 확인하라

25/37

Page 26: 부동소수점 (FLP)

도메인 체크

26/37

수학 함수에서 도메인 에러나 영역 에러를 찾고 예방하라

수학 함수에 전달되는 인자 값이 함수 정의 시 지정된 도메인 안에 있음을 보장해 예방

if( /* 인자 값이 도메인 에러를 유발할 수 있음 */) {/* 도메인 에러 처리 */

} else {

/* 계산수행 */ }

Page 27: 부동소수점 (FLP)

범위 체크

27/37

수학 함수에서 도메인 에러나 영역 에러를 찾고 예방하라

함수 도메인 범위

acos(x), asin(x) -1 <= x && x <= 1 없음

atan2(y, x) x != 0 || y != 0 없음

acosh(x) x >= 1 없음

atanh(x) -1 < x && x < 1 없음

cosh(x), sinh(x) 없음 있음

exp(x), exp2(x), expml(x)

없음 있음

ldexp(x, exp) 없음 있음

log(x), log10(x), log2(x) x > 0 없음

log1p(x) x > -1 없음

ilogb(x), logb(x) x != 0 있음

scalbn(x, n), scalbln(x, n) 없음 있음

hypot(x, y) 없음 있음

Page 28: 부동소수점 (FLP)

범위 체크

28/37

수학 함수에서 도메인 에러나 영역 에러를 찾고 예방하라

함수 도메인 범위

pow(x, y) x>0||(x==0&&y>0)||(x<0&&y 는 정수 )

있음

sqrt(x) x >= 0 없음

erfc(x) 없음 있음

lgammma(x), tgammma(x)

x!=0&&!(x<0&&x 는 정수 )

있음

lrint(x), lround(x) 없음 있음

fmod(x, y) y != 0 없음

nextafter(x, y), nexttoward(x, y)

없음 있음

fdim(x, y) 없음 있음

fma(x, y, z) 없음 있음

Page 29: 부동소수점 (FLP)

FLP32-C 부적절한 코드 예

double x;double result;/* x 초기화 */result = sqrt(x);

29/37

=> x 의 제곱근 구함

수학 함수에서 도메인 에러나 영역 에러를 찾고 예방하라

=> x 가 음수인 경우 에러 발생

Page 30: 부동소수점 (FLP)

FLP32-C 해결방법

double x;double result;/* x 초기화 */if (isless(x,0))

/* 범위 에러 처리 */else result = sqrt(x);

30/37

수학 함수에서 도메인 에러나 영역 에러를 찾고 예방하라

Page 31: 부동소수점 (FLP)

규칙

FLP30-C 부동소수점 변수를 루프 카운터로 사용하지 마라 FLP31-C 함수에 복소수를 사용하면서 실제 값을 얻을 거라

기대하지 마라 FLP32-C 수학 함수에서 도메인 에러나 영역 에러를 찾고

예방하라

FLP33-C 부동소수점 연산용 정수는 먼저 부동소수점으로 바꿔라

FLP34-C 부 동 소 수 점 변 환 이 새 로 운 타 입 의 범 위 안 에 들어가는지 확인하라

31/37

Page 32: 부동소수점 (FLP)

FLP33-C 부적절한 코드 예

short a = 533;int b = 6789;long c = 466438237;

float d = a / 7;double e = b / 30;double f = c * 789;

32/37

부동소수점 연산용 정수는 먼저 부동소수점으로 바꿔라

=> d=76.0 e=226.0 f=368019768993=> d, e, f 가 부정확하게 초기화되어 값의일 부 가 정 수 근 처 에 서 잘 리 거 나 오버플로우 발생 가능

Page 33: 부동소수점 (FLP)

FLP33-C 해결방법

short a = 533;int b = 6789;long c = 466438237;

float d = a / 7.0;double e = b / 30.0;double f = double(c) * 789;

33/37

부동소수점 연산용 정수는 먼저 부동소수점으로 바꿔라

Page 34: 부동소수점 (FLP)

규칙

FLP30-C 부동소수점 변수를 루프 카운터로 사용하지 마라 FLP31-C 함수에 복소수를 사용하면서 실제 값을 얻을 거라

기대하지 마라 FLP32-C 수학 함수에서 도메인 에러나 영역 에러를 찾고

예방하라 FLP33-C 부동소수점 연산용 정수는 먼저 부동소수점으로

바꿔라

FLP34-C 부동소수점 변환이 새로운 타입의 범위 안에 들어가는지 확인하라

34/37

Page 35: 부동소수점 (FLP)

FLP34-C 부적절한 코드 예

float f1;int i1;/* f1 초기화 */i1 = f1;

35/37

부동소수점 변환이 새로운 타입의 범위 안에 들어가는지 확인하라

=> f1 의 정수 부분이 INT_MAX 보다 큰 경우 정의되지 않음

Page 36: 부동소수점 (FLP)

FLP34-C 해결방법

float f1;int i1;/* f1 초기화 */if ( f1 > (float) INT_MAX || f1 < (float) INT_MIN) {

else {i1 = f1;

}

36/37

부동소수점 변환이 새로운 타입의 범위 안에 들어가는지 확인하라

Page 37: 부동소수점 (FLP)

규칙

FLP30-C 부동소수점 변수를 루프 카운터로 사용하지 마라 FLP31-C 함수에 복소수를 사용하면서 실제 값을 얻을 거라

기대하지 마라 FLP32-C 수학 함수에서 도메인 에러나 영역 에러를 찾고

예방하라 FLP33-C 부동소수점 연산용 정수는 먼저 부동소수점으로

바꿔라 FLP34-C 부 동 소 수 점 변 환 이 새 로 운 타 입 의 범 위 안 에

들어가는지 확인하라

37/37