|
안녕하세요. heredity입니다.
질문하신 내용은 유효자리를 벗어나는 실수 연산이 그 원인인 것으로 추정됩니다.
point.x * cos0의 결과 값인 3.06151588455594E-16F는 상당히 작은 값인데,
double형이 이 값만을 가질 경우 실수 유효 범위(자리)안에 들어가기 때문에 표현(저장) 가능하나
실수 -5.0과 더해지면서 그 값이 유효자리를 벗어나게 되며,
double 변수에 보관하면 -5로 기록됩니다(이 부분은 실제로 해보지 않으면 잘 이해가 안 될 수도 있습니다.)
반면 실행 결과를 double에 보관하기전 정수화 시키면
-4.9999999...를 정수화 해서 -4가 되는 것으로 추정됩니다.
불행히도 이 연산에 대한 실행코드는 Co-processor에게 전달되어 처리되므로
직접 확인은 불가능 했으나 아래의 예를 보면 그 원인을 짐작 할 수 있으리라 봅니다.
double dblFive = -5;
double dblCos = 3.06151588455594E-16F;
double dblAdd = dblFive + dblCos;
int nX1 = dblFive + dblCos; // nX1 = -4, 실행 중간 결과를 확인해 보면 좋으련만...
int nX2 = dblAdd; // nX2 = -5
int nX3 = (int) (dblFive + dblCos); // nX3 = -4
double dblM = -5 + 3.06151588455594E-16F; // dblM = -5;
소스 우측 부분에 결과값을 표시하여 두었으니 확인하시기 바랍니다.
행복하세요.
WARSHIP 님이 쓰신 글 :
:
: class TPoint
: {
: public:
: TPoint() {}
: TPoint(int _x, int _y) : x(_x), y(_y) {}
: TPoint(POINT& pt)
: {
: x = pt.x;
: y = pt.y;
: }
: operator POINT() const
: {
: POINT pt;
: pt.x = x;
: pt.y = y;
: return pt;
: }
: int x;
: int y;
: };
:
: template < typename PT_Type >
: struct Special_Rotate /* Rotate point at special origin */
: {
: static PT_Type rotate( PT_Type &point, double &angle , PT_Type &origin )
: {
:
: double cos0=cos(angle) , sin0=sin(angle);
:
: // Case 1
: double nx,ny;
: nx = (point.x * cos0) + (point.y * -sin0) + ( -origin.x * cos0 ) + ( origin.y * sin0 ) + origin.x;
: ny = (point.x * sin0) + (point.y * cos0) + ( -origin.x * sin0 ) + ( -origin.y * cos0 ) + origin.y;
: PT_Type pt1(nx,ny);
:
: // Case 2
: PT_Type pt2;
: pt2.x = (point.x * cos0) + (point.y * -sin0) + ( -origin.x * cos0 ) + ( origin.y * sin0 ) + origin.x;
: pt2.y = (point.x * sin0) + (point.y * cos0) + ( -origin.x * sin0 ) + ( -origin.y * cos0 ) + origin.y;
:
: printf(" Case 1 : [%2d,%2d]\n",pt1.x , pt1.y);
: printf(" Case 2 : [%2d,%2d]\n",pt2.x , pt2.y);
: return pt1;
: }
: };
:
: int main()
: {
: TPoint a,b(5,5);
: a = Special_Rotate<TPoint>::rotate(b,M_PI_2,TPoint(0,0));
: return 0;
: }
:
:
: 위의 화일을 컴파일 하면
: 결과는 아래와 같습니다.
:
: ---------- Excute ----------
: Case 1 : [-5, 5]
: Case 2 : [-4, 5]
: 출력 완료 (0초 경과) - 정상 종료
:
: 1번의 경우에는 계산값이 double형 변수에 담겼다가 형변환이 되면서 pt1으로 저장되구요.
: 2번의 경우에는 계산값이 double형 임시변수(컴파일러가 만들어주는?)에서 바로 형변환이 되면서 pt2로 들어가
: 는걸로 알고 있는데요 ( More Effective c++ .. )
: 같은 계산식인데도 불구하고 두결과가 저렇게 차이가 나네요.
:
: 임시변수나 객체는 컴파일러가 최적화 할수 있으니 되도록이면 임시변수나 객체를 쓰라고 읽은 기억도 있는데
: 위와 같은 결과가 나오니까 좀 아이러니 하고 , 이해가 안되서 이렇게 질문을 올립니다.
: 특별한 컴파일 옵션을 주어야 하는지. 아니면 굳이 Case1번처럼 코딩을 해야 하는지
: 궁금하네요. 그럼 좋은 하루 보내시구요~ 답변좀 부탁드립니다. 의견도 좋습니다 ^^;
|