programing

부동 소수점 숫자의 기호, 가수 및 지수를 얻는 방법

newsource 2022. 8. 28. 09:43

부동 소수점 숫자의 기호, 가수 및 지수를 얻는 방법

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);)를 참조해 주세요.

다른 옵션은%aprintf().

당당입니다.&잘못된 부분을 입력한다.다음 중 하나:

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.  */
  1. 여러 가지 작업을 수행하는 기능은 만들지 마십시오.
  2. 마스크 후 시프트하지 말고 시프트 후 마스크.
  3. 캐시 파괴가 느리고 오류가 발생하기 쉬우므로 값을 불필요하게 변환하지 마십시오.
  4. 마법의 숫자를 사용하지 마세요.
/* 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