IEEE-754 형식 정수를 부동 소수점으로 출력하는 방법
-
13-09-2019 - |
문제
IEEE-754 형식을 사용하여 부동 소수점을 나타내는 부호 없는 긴 정수 값이 있습니다.C++에서 부동 소수점으로 인쇄하는 가장 빠른 방법은 무엇입니까?
한 가지 방법을 알고 있지만 C++에 더 나은 편리한 유틸리티가 있는지 궁금합니다.
내가 아는 방식의 예는 다음과 같습니다.
union
{
unsigned long ul;
float f;
} u;
u.ul = 1084227584; // in HEX, this is 0x40A00000
cout << "float value is: " << u.f << endl;
(이렇게 하면 "float 값은 다음과 같습니다.5")
해결책
당신이 제안한 노조 방법은 대부분의 사람들이 취할 일반적인 경로입니다. 그러나 기술적으로입니다 정의되지 않은 행동 C/C ++에서 가장 최근에 작성된 것과는 노조와 다른 멤버를 읽습니다. 그러나 그럼에도 불구하고 거의 모든 컴파일러 중에는 잘 지원됩니다.
캐스팅 포인터 Jon Skeet가 제안했습니다, 나쁜 생각입니다 엄격한 별칭 C.의 규칙은 공격적인 최적화 컴파일러가 유형의 포인터를 가정하기 때문에 잘못된 코드를 생성합니다. unsigned long *
그리고 float *
서로 별칭을하지 않을 것입니다.
표준 준수 측면에서 가장 올바른 방법은 (즉, 정의되지 않은 행동을 불러 일으키는 것이 아니라) char*
, 엄격한 별칭 규칙은 a char*
별명에 대한 포인터 다른 유형의 포인터 :
unsigned long ul = 0x40A00000;
float f;
char *pul = (char *)&ul; // ok, char* can alias any type
char *pf = (char *)&f; // ok, char* can alias any type
memcpy(pf, pul, sizeof(float));
솔직히 말해서, 나는 단지 노조 방법과 함께 갈 것입니다. 위의 CellPerformance.com 링크에서 :
그것은 매우 일반적인 관용구이며 모든 주요 컴파일러에 의해 잘 지원됩니다. 실질적인 문제로, 어떤 순서로든 노조의 모든 구성원에게 읽고 쓰는 것은 수용 가능한 관행입니다.
다른 팁
크기 (long) == sizeof (float) 인 32 비트 기계 또는 기계에서만 작동합니다. 최신 기계에서는 대신 INT를 사용하고 싶을 수도 있습니다.이 트릭을 수행하는 경우 실제로주의를 기울여야합니다.
나는 Jon Skeet과 같은 것을 생각하고 있었지만 그는 나를 이겼습니다. 그러나 나는 그가 한 것보다 조금 더 간결하게 할 것입니다.
cout << "float value is: " << *((float *) &ulValue)) << endl;
당신은 서명되지 않은 길고에 대한 포인터를 얻은 다음, float의 포인터로서 포인터를 부동산으로 인출하면 플로트 값을 생성합니다.
C ++ 에서이 작업을 수행하고 있으므로 이전 C 스타일 캐스트 대신 reinterpret_cast를 사용하는 것이 더 명확합니다.
cout << "float value is: " << *(reinterpret_cast<float *>(&ulValue)) << endl;
편집하다:이전에는 이것이 "그저 불쾌한 일"이라고 생각했지만, 생각했던 것보다 더 나쁜 것으로 나타났습니다. 자세한 내용은 댓글을 참조하세요.나는 이 접근 방식을 권장하지 않지만 가능성(그리고 주의 사항!)을 문서화하기 위해 여기에 남겨 둡니다.
포인터를 사용할 수 있습니다.
long ul = 1084227584;
float* fp = (float*) &ul;
float f = *fp;
(이것은 한 줄로 압축할 수 있지만 그렇지 않은 것이 더 명확하다고 생각합니다.)
기본적으로는 노조랑 똑같습니다...관련된 유형의 크기를 확신하지 않는 한 똑같이 위험합니다.
플랫폼이 이를 지원하는 경우 정수 및 부동 소수점 유형 모두에 대해 크기별 유형 이름을 사용해야 합니다.
Swegi는 올바른 방향을 가졌지 만 하나의 캐릭터를 놓쳤다. 올바른 방법은
long l = 1084227584L
float f = reinterpret_cast<float&>(l);