ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • IEEE 754 single precision : binary32
    개발하면서/etc 2011. 8. 11. 23:01
    반응형

    참조 :  IEEE 754 floating point Wiki

    IEEE 754 blog

    정수를 넣으면 어떻게 비트변환이 되는지 보여줌

    어떻게 변환되는지 단계별로 잘 설명한사이트

     

    위의 자료를 통하여 IEEE 754가 어떤 규칙을 통해 부동 소수점을 표현하는지 알게 되었다.

    소수부분에서 10진수를 2진수로 변환하는 걸 나는 아래와 같이 생각하고 있었다.

    float input;
    printf("input converting float Number :");
    scanf("%f", &input);
    
    char binary[15+1];
    int binary_idx;
    float fraction = 0.5f;
    binary_idx = 0
    
    while (input != 0.0f && binary_idx < 15) {
    	if (input >= fraction) {
    		binary[binary_idx] = '1';
    		input -= fraction;
    	}
    	else 
    		binary[binary_idx] = '0';
    	fraction /= 2;
    }
    binary[binary_idx] = '\0';
    printf("bit : %s\n", binary);
    

     

    0.5, 0.25, 0.125를 원래정수에 빼보면서 0이 나올때까지 loop를 돌리는것이다.

    그런데 이것 저것 예제를 보다가 다른 방법으로 구하는게 있어서 그것대로 구현을 해봤다.

    
    printf("input converting float Number :");
    scanf("%f", &input);
    char binary[15+1];
    int binary_idx;
    binary_idx = 0;
    input *= 2;
    while (input != 1.0f && binary_idx < 15) {  
    	if (input > 1.0f) {     
    		binary[binary_idx] = '1';       
    		input -= 1.0f;  
    	}   
    	else        
    		binary[binary_idx] = '0';   
    	binary_idx++;   
    	input *= 2;
    	}
    if (input == 1.0f)  
    	binary[binary_idx++] = '1';
    binary[binary_idx] = '\0';
    printf("bit : %s\n", binary);
    ]]>
    

    다른점은 나누기/곱하기 연산.....그리고 fraction 유/무  괜시리 곱하기 연산이 나누기 연산보다는 빠를것 같다. 캬.....수학....;;

     

    다시 IEEE754로 와서 Not-a-Number 는 아래와 같다.

    ±0 ÷ ±0 NaN
    Infinity - Infinity NaN
    ±Infinity ÷ ±Infinity NaN
    ±Infinity × 0 NaN

    NAN은 아래와 같이 표현 한다고 한다.

     

    0 11..11 00..01
    :
    01..11
    SNaN
    0 11..11 10..00
    :
    11..11
    QNaN
    1 11..11 00..01
    :
    01..11
    SNaN
    1 11..11 10..00
    :
    11.11
    QNaN

     

    이걸 학습한 본래의 목적은 아래와 같은 결과가 나와서 왜?? 그런지 또 어떻게 하면 해결할수 있을지에 대한 의문을 풀기 위함이었다.

    byte input = 'F';
    input = SmallFloat.floatToByte315(0.75f);
    System.out.println("input :" + input);
    System.out.println("finput :" + SmallFloat.byte315ToFloat(input));
    //결과 : input :122
    //      finput :0.75
    
    byte input = 'F';
    input = SmallFloat.floatToByte315(0.75f);
    System.out.println("input :" + input);
    System.out.println("finput :" + SmallFloat.byte315ToFloat(input));
    //결과 : input :121
            finput :0.625
    

    왜 저런 수가 나왔는지는 간단하게 살펴보면~!!    (0.75를 예로)

    0.75를 2진수로
    0.75 * 2 = 1.5   (1)
    0.5  * 2  = 1.0   (1) 
    0.75(10) ->  0.11(2)       nomalize :    1.1 * (2^-1)   
    Mantissa  :  1                Exponent : (-1) + 127 = 126      Sign bit = 0
    so  0011 1111   0100 0000   0000 0000   0000 0000
    아래 함수에서 bits에 0011 1111   0100 0000   0000 0000   0000 0000값이 저장되고 return결과가 122
     

    public static byte floatToByte315(float f) {
        int bits = Float.floatToRawIntBits(f);
        int smallfloat = bits >> (24-3);
        if (smallfloat < (63-15)<<3) {
          return (bits<=0) ? (byte)0 : (byte)1;
        }
        if (smallfloat >= ((63-15)<<3) + 0x100) {
          return -1;
        }
        return (byte)(smallfloat - ((63-15)<<3));
     }
    

    0.74는 0.5(1) + 0.25(0) + .....계속 가다보니 23bit 를 넘어섰고 Mantisa의 범위, 23개에서 자른것이다.

    컴퓨터에서 말하는 float 자료형은 int같이 정확한 수 개념이 아니라 대충 이럴거 같다, 라는 것이기 때문에

    원하는 결과를 얻지 못하는것이다.

     

    0.75, 0.625, 0.5는 자르는것 없이 정확하게 표현이 되는데 다른 수들은 어떻게 풀어 나가면 좋을까?

    생각난건 1bit를 어느쪽에 가깝냐.....라는 bit로 사용하는건 어떨까?

    1 이면 현재 Mantisa범위에서 윗단계와 가깝고, 0으면 그냥 현재 Mantisa 범위와 같다....

    이렇게 하면 0.74도 0.75로 나오지 않을까.......

     

    조사한건 많았는데 막상 이렇게 블로그에 올리려고 하니, 주저리 떠들기나 하고있다.

    아직 완벽하게 이해하지 않는것 같다...;;; 씁쓸하네...

    반응형

    댓글

Designed by Tistory.