참조 : IEEE 754 floating point Wiki , IEEE 754 blog , 정수를 넣으면 어떻게 비트변환이 되는지 보여줌
어떻게 변환되는지 단계별로 잘 설명한사이트
위의 자료를 통하여 IEEE 754가 어떤 규칙을 통해 부동 소수점을 표현하는지 알게 되었다.
소수부분에서 10진수를 2진수로 변환하는 걸 나는 아래와 같이 생각하고 있었다.
그런데 이것 저것 예제를 보다가 다른 방법으로 구하는게 있어서 그것대로 구현을 해봤다.
다른점은 나누기/곱하기 연산.....그리고 fraction 유/무
괜시리 곱하기 연산이 나누기 연산보다는 빠를것 같다. 캬.....수학....;;
다시 IEEE754로 와서
Not-a-Number 는 아래와 같다. 숫자가 아니라는거.
NAN은 아래와 같이 표현 한다고 한다.
이걸 학습한 본래의 목적은 아래와 같은 결과가 나와서 왜?? 그런지 또 어떻게 하면 해결할수 있을지에 대한 의문을 풀기 위함이었다.
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로 나오지 않을까.......
조사한건 많았는데 막상 이렇게 블로그에 올리려고 하니, 주저리 떠들기나 하고있다.
아직 완벽하게 이해하지 않는것 같다...;;; 씁쓸하네...
어떻게 변환되는지 단계별로 잘 설명한사이트
위의 자료를 통하여 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를 돌리는것이다.
그런데 이것 저것 예제를 보다가 다른 방법으로 구하는게 있어서 그것대로 구현을 해봤다.
다른점은 나누기/곱하기 연산.....그리고 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로 나오지 않을까.......
조사한건 많았는데 막상 이렇게 블로그에 올리려고 하니, 주저리 떠들기나 하고있다.
아직 완벽하게 이해하지 않는것 같다...;;; 씁쓸하네...