Programmer BS Blog

 by BSPFP

Textile 포매터 문법 요약

글 보관함

Total131048
Today168
Yesterday432
회사 동료가 와서 이런 문제를 어떻게 해결해야 하는지 물어보네요.
float f = 19.85f;
double d1 = double(f);
double d2 = 19.85;

이렇게 하면 d1의 값이 19.850000381469727 게 됩니다.
d2의 값이 19.850000000000001 인 것과는 완전 다르죠...
문제는 이렇게 구해진 d1을 수식에서 백분율로 사용하면서 생겼습니다.
원치않는 수치가 나오는 것이죠.

디스어셈블리로 코드를 확인하면 별 다른 것 없이
형을 변환하는 명령을 호출할 뿐입니다.
즉, 이건 컴파일러의 문제가 아니라는 것이죠.

그래서 이런 문제를 해결하면서 이전 코드의 수정을 최소화 한다면...
이런 방법 정도로 생각됩니다.
(BS에게 질문을 던진 동료는 그냥 백분율이기 때문에 100 곱해서 정수로 형변환해서 우회하기로 했지만요...)
#include 

using namespace std;

class F32
{
public:
	F32() : f(0.0f) {}
	F32(float s) : f(s) {}

	F32& operator=(float const & s) { f = s; return *this; }
	double operator*(double const & s) const { return s * double(*this); }
	double operator/(double const & s) const { return s / double(*this); }
	double operator+(double const & s) const { return s + double(*this); }
	double operator-(double const & s) const { return s - double(*this); }
	bool operator==(double const & s) const { return (double(*this) == s); }
	operator float() const { return f; }

	operator double() const
	{
		long long n = long long(f);
		return n + long long((f - n) * 1000000) / 1000000.0;
	}

private:
	float f;
};

int main(void)
{
	float f = 19.85f;
	F32 tf = 19.85f;
	long long d1 = long long(double(tf) * 3370000000000LL);
	long long d2 = long long(tf * 1.0 * 3370000000000LL);
	long long d3 = long long(double(f) * 3370000000000LL);
	long long d4 = long long(f * 1.0 * 3370000000000LL);
	cout << d1 << endl;
	cout << d2 << endl;
	cout << d3 << endl;
	cout << d4 << endl;
	cout << (tf == 19.85) << endl;

	/*
		output:
			66894500000000
			66894500000000
			66894501285552
			66894501285552
			1
	*/
	return 0;
}


결과는 잘 나오는데 어셈블리 코드를 보면 상당히 늘어나는 것을 알 수 있습니다.

return (double)f;
mov         rax,qword ptr [this]
movd        xmm0,dword ptr [rax]
cvtps2pd    xmm0,xmm0


long long n = long long(f);
return n + long long((f - n) * 1000000) / 1000000.0;
mov         rax,qword ptr [this]
cvttss2si   rax,dword ptr [rax]
mov         qword ptr [n],rax
pxor        xmm0,xmm0
cvtsi2sd    xmm0,qword ptr [n]
pxor        xmm1,xmm1
cvtsi2ss    xmm1,qword ptr [n]
mov         rax,qword ptr [this]
movss       xmm2,dword ptr [rax]
subss       xmm2,xmm1
movaps      xmm1,xmm2
mulss       xmm1,dword ptr [__real@49742400 (13F0E796Ch)]
cvttss2si   rax,xmm1
pxor        xmm1,xmm1
cvtsi2sd    xmm1,rax
divsd       xmm1,mmword ptr [__real@412e848000000000 (13F0E7940h)]
addsd       xmm0,xmm1


처음부터 double을 쓰면 문제가 안되겠지만...
기존 시스템이 float를 쓰고 있고 여기에 추가되는 일부 코드가 long long과 double을 사용하는 경우에는 발생할 수 있는 문제입니다.

Trackback Address :: http://bspfp.pe.kr/trackback/320

PREV 1 ... 5 6 7 8 9 10 11 12 13 ... 301 NEXT