부동 소수점 숫자의 기호, 가수 및 지수를 얻는 방법
2개의 프로세서에서 실행되고 있는 프로그램이 있는데, 그 중 하나는 부동소수점을 지원하지 않습니다.따라서 프로세서의 고정점을 사용하여 부동소수점 계산을 수행해야 합니다.이를 위해 부동소수점 에뮬레이션 라이브러리를 사용합니다.
부동소수점을 지원하는 프로세서의 부동소수점 숫자 기호, 맨티사 및 지수를 먼저 추출해야 합니다.그래서 제 질문은 어떻게 단일 정밀 부동 소수점 숫자의 부호, 가수, 지수를 얻을 수 있는가입니다.
이 그림의 형식에 따라
그게 내가 지금까지 해온 일이지만, 부호만 빼면, 가수와 지수 둘 다 맞지 않아요.뭔가 빠진 것 같아
void getSME( int& s, int& m, int& e, float number )
{
unsigned int* ptr = (unsigned int*)&number;
s = *ptr >> 31;
e = *ptr & 0x7f800000;
e >>= 23;
m = *ptr & 0x007fffff;
}
조합으로 출연하는 게 더 낫다고 생각해요, 더 명확합니다.
#include <stdio.h>
typedef union {
float f;
struct {
unsigned int mantisa : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} parts;
} float_cast;
int main(void) {
float_cast d1 = { .f = 0.15625 };
printf("sign = %x\n", d1.parts.sign);
printf("exponent = %x\n", d1.parts.exponent);
printf("mantisa = %x\n", d1.parts.mantisa);
}
http://en.wikipedia.org/wiki/Single_precision에 근거한 예
제 조언은 규칙 0을 고수하고 이 정도면 충분하다면 표준 라이브러리를 다시 실행하지 말라는 것입니다.math.h(표준 C++의 cmath)와 함수 frexp, frexpf, frexpl을 살펴봅니다. frexp, frexpl은 유의 및 지수 부분에서 부동 소수점 값(이중, 부동 또는 긴 이중)을 끊습니다.부호 추출을 위해 부호 비트를 사용할 수 있습니다(math.h / cmath 또는 복사 부호(C++11만 해당).다른 의미론에서는 modf와 ilogb/bn이 있습니다.이러한 기능은 C++11에서 사용할 수 있습니다.http://en.cppreference.com/w/cpp/numeric/math/logb에서는 비교하고 있습니다만, 문서에서는 이러한 모든 함수가 +/-inf 및 NaN에서 어떻게 동작하는지는 찾을 수 없었습니다.마지막으로 비트마스크를 정말로 사용하고 싶다면(예를 들어, 정확한 비트를 알아야 하며, 프로그램이 다른 표현을 가진 다른 NaN을 가질 수 있으며, 위의 함수를 신뢰하지 않음), 적어도 float의 매크로를 사용하여 모든 것을 플랫폼에 의존하지 않도록 해야 합니다.
부동소수를 직접 지원하는 CPU에서 사용되는 부동소수점 숫자의 형식을 찾아 각 부분으로 나눕니다.가장 일반적인 형식은 IEEE-754입니다.
또는 몇 가지 특수 기능을 사용하여 부품을 구할 수도 있습니다(double frexp(double value, int *exp);
★★★★★★★★★★★★★★★★★」double ldexp(double x, int exp);
)를 참조해 주세요.
당당입니다.&
잘못된 부분을 입력한다.다음 중 하나:
s = *ptr >> 31;
e = *ptr & 0x7f800000;
e >>= 23;
m = *ptr & 0x007fffff;
, ★★★★★★★★★★★★★★★★★★★★★★.&
설정되지 않은 비트는 제로 아웃됩니다.이 경우, 지수를 구할 때 부호 비트를 0으로 하고, 가수 값을 얻을 때 부호 비트와 지수를 0으로 합니다.
마스크는 사진에서 직접 가져온 것입니다.따라서 지수 마스크는 다음과 같습니다.
0 11111111 00000000000000000000000
가수 마스크는 다음과 같습니다.
0 00000000 11111111111111111111111
헤더 "glibc-headers"를 합니다.#include <ieee754.h>
이치노 §:
union ieee754_double
{
double d;
/* This is the IEEE 754 double-precision format. */
struct
{
#if __BYTE_ORDER == __BIG_ENDIAN
unsigned int negative:1;
unsigned int exponent:11;
/* Together these comprise the mantissa. */
unsigned int mantissa0:20;
unsigned int mantissa1:32;
#endif /* Big endian. */
#if __BYTE_ORDER == __LITTLE_ENDIAN
# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
unsigned int mantissa0:20;
unsigned int exponent:11;
unsigned int negative:1;
unsigned int mantissa1:32;
# else
/* Together these comprise the mantissa. */
unsigned int mantissa1:32;
unsigned int mantissa0:20;
unsigned int exponent:11;
unsigned int negative:1;
# endif
#endif /* Little endian. */
} ieee;
/* This format makes it easier to see if a NaN is a signalling NaN. */
struct
{
#if __BYTE_ORDER == __BIG_ENDIAN
unsigned int negative:1;
unsigned int exponent:11;
unsigned int quiet_nan:1;
/* Together these comprise the mantissa. */
unsigned int mantissa0:19;
unsigned int mantissa1:32;
#else
# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
unsigned int mantissa0:19;
unsigned int quiet_nan:1;
unsigned int exponent:11;
unsigned int negative:1;
unsigned int mantissa1:32;
# else
/* Together these comprise the mantissa. */
unsigned int mantissa1:32;
unsigned int mantissa0:19;
unsigned int quiet_nan:1;
unsigned int exponent:11;
unsigned int negative:1;
# endif
#endif
} ieee_nan;
};
#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */
- 여러 가지 작업을 수행하는 기능은 만들지 마십시오.
- 마스크 후 시프트하지 말고 시프트 후 마스크.
- 캐시 파괴가 느리고 오류가 발생하기 쉬우므로 값을 불필요하게 변환하지 마십시오.
- 마법의 숫자를 사용하지 마세요.
/* NaNs, infinities, denormals unhandled */
/* assumes sizeof(float) == 4 and uses ieee754 binary32 format */
/* assumes two's-complement machine */
/* C99 */
#include <stdint.h>
#define SIGN(f) (((f) <= -0.0) ? 1 : 0)
#define AS_U32(f) (*(const uint32_t*)&(f))
#define FLOAT_EXPONENT_WIDTH 8
#define FLOAT_MANTISSA_WIDTH 23
#define FLOAT_BIAS ((1<<(FLOAT_EXPONENT_WIDTH-1))-1) /* 2^(e-1)-1 */
#define MASK(width) ((1<<(width))-1) /* 2^w - 1 */
#define FLOAT_IMPLICIT_MANTISSA_BIT (1<<FLOAT_MANTISSA_WIDTH)
/* correct exponent with bias removed */
int float_exponent(float f) {
return (int)((AS_U32(f) >> FLOAT_MANTISSA_WIDTH) & MASK(FLOAT_EXPONENT_WIDTH)) - FLOAT_BIAS;
}
/* of non-zero, normal floats only */
int float_mantissa(float f) {
return (int)(AS_U32(f) & MASK(FLOAT_MANTISSA_BITS)) | FLOAT_IMPLICIT_MANTISSA_BIT;
}
/* Hacker's Delight book is your friend. */
추출하는 유니언 타입에 대해서는, 다음의 헤더를 참조해 주세요.float
,double
★★★★★★★★★★★★★★★★★」long double
(handled.) , ('Endianness handled' ) 。다음은 발췌입니다.
/*
** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
** Single Precision (float) -- Standard IEEE 754 Floating-point Specification
*/
# define IEEE_754_FLOAT_MANTISSA_BITS (23)
# define IEEE_754_FLOAT_EXPONENT_BITS (8)
# define IEEE_754_FLOAT_SIGN_BITS (1)
.
.
.
# if (IS_BIG_ENDIAN == 1)
typedef union {
float value;
struct {
__int8_t sign : IEEE_754_FLOAT_SIGN_BITS;
__int8_t exponent : IEEE_754_FLOAT_EXPONENT_BITS;
__uint32_t mantissa : IEEE_754_FLOAT_MANTISSA_BITS;
};
} IEEE_754_float;
# else
typedef union {
float value;
struct {
__uint32_t mantissa : IEEE_754_FLOAT_MANTISSA_BITS;
__int8_t exponent : IEEE_754_FLOAT_EXPONENT_BITS;
__int8_t sign : IEEE_754_FLOAT_SIGN_BITS;
};
} IEEE_754_float;
# endif
또, 의 변환 방법의 데모를 참조해 주세요.double
값을 문자열 형식으로 지정합니다.
또한 섹션 1.2.1.1.4.2 - C/CPP 레퍼런스 북의 부동소수점 유형 메모리 레이아웃을 참조하십시오.이것은 모든 부동소수점 유형의 메모리 표현/레이아웃과 실제 IEEE 754 부동소수점 사양에 따른 디코딩 방법(그림 포함)에 대해 매우 잘 설명하고 있습니다.
또, 매우 뛰어난 자원과의 링크도 있어, 한층 더 자세하게 설명하고 있습니다.
언급URL : https://stackoverflow.com/questions/15685181/how-to-get-the-sign-mantissa-and-exponent-of-a-floating-point-number
'programing' 카테고리의 다른 글
이미지를 잘라내기 영역 내에서만 표시(cropper-js) (0) | 2022.08.28 |
---|---|
vuejs-datepicker의 너비 및 높이를 변경할 수 없습니다. (0) | 2022.08.28 |
Vuex는 개발 도구를 통해 수동으로 커밋될 때까지 변경을 커밋하지 않습니다. (0) | 2022.08.28 |
Java에서 Enum start 값을 설정할 수 있습니까? (0) | 2022.08.28 |
Server Socket accept() 메서드를 중단하려면 어떻게 해야 합니까? (0) | 2022.08.28 |