2011-03-09
浮動小数点数のビット列
浮動小数点数のビット列を解析する必要があったのでついでに解析プログラムを作ってみた。
以下のようにして使う。
# コンパイル $ gcc ./fl.c -o fl # 解析 $ ./f 3.402823e+37 * 受け取った数(文字列表現) :3.402823e+37 * 受け取った数(float型表現) :34028229593250485068252812361638871040.000000 * 受け取った数(double型表現):34028229999999999496011500909022412800.000000 -------------------------------------------------------------------- * float 値 :34028229593250485068252812361638871040.000000 ビット :01111101110011001100110011001010 符号部 :+1 (1bit:0) 指数部 :124 (8bit:11111011) 仮数部 :1.5033162 (23bit:10011001100110011001010) 指数表現 :3.402823e+37 計算式 :+1 * 1.5033162 * 2の124乗 -------------------------------------------------------------------- * double 値 :34028229999999999496011500909022412800.000000 ビット :0100011110111001100110011001100101000101001000100100011101010000 符号部 :+1 (1bit:0) 指数部 :124 (11bit:10001111011) 仮数部 :1.2702158359316304 (52bit:1001100110011001100101000101001000100100011101010000) 指数表現 :3.402823e+37 計算式 :+1 * 1.2702158359316304 * 2の124乗 --------------------------------------------------------------------
以下、プログラム。
#include <stdio.h> #include <stdlib.h> #include <float.h> #include <stdint.h> #define float_t float #define float_size (sizeof(float_t) * 8) #define double_t double #define double_size (sizeof(double_t) * 8) #define formatstr_basic \ "* 受け取った数(文字列表現) :%s\n" \ "* 受け取った数(float型表現) :%f\n" \ "* 受け取った数(double型表現):%f\n" #define formatstr_float \ ( \ "* float\n" \ "値 :%f\n" \ "ビット :%s\n" \ "\n" \ "符号部 :%-8s (1bit:%s)\n" \ "指数部 :%-8d (8bit:%s)\n" \ "仮数部 :1.%-8llu (23bit:%s)\n" \ "\n" \ "指数表現 :%e\n" \ "計算式 :%s * 1.%llu * 2の%d乗\n" \ ) #define formatstr_double \ ( \ "* double\n" \ "値 :%f\n" \ "ビット :%s\n" \ "\n" \ "符号部 :%-16s (1bit:%s)\n" \ "指数部 :%-16d (11bit:%s)\n" \ "仮数部 :1.%-16llu (52bit:%s)\n" \ "\n" \ "指数表現 :%e\n" \ "計算式 :%s * 1.%llu * 2の%d乗\n" \ ) #define str_separator "--------------------------------------------------------------------" union ufloat { uint32_t i; float_t f; }; union udouble { uint64_t i; double_t f; } ; /* === util */ void usage(char *scriptname) { printf("usage : %s <number>\n" , scriptname); } #define show_error(a) fprintf a /* === parse_double */ void parse_double(uint8_t **s , uint64_t x) { int i ; uint8_t *s0 = *s; for (i=double_size-1; i >= 0 ; i--) { s0[i] = (uint8_t)(x & 1); x >>= 1; } } /* === parse_float */ void parse_float(uint8_t **s , uint32_t x) { int i ; uint8_t *s0 = *s; for (i=float_size-1; i >= 0 ; i--) { s0[i] = (uint8_t)(x & 1); x >>= 1; } } /* === alloc_bitstr */ char* alloc_bitstr(uint8_t *s , int size) { int i ; char *s0 = (char*)malloc( sizeof(char) * (size + 1) ); for (i=0;i<size;i++) s0[i] = (s[i] ? '1' : '0'); s0[size] = '\0'; return s0; } /* === bit2uint16 */ int16_t bit2uint16(char *bitstr) { char c0; int16_t i = 0; while(c0 = *(bitstr++)) { i <<= 1; if (c0 == '1') i++; } return i; } /* === bit2uint64 */ uint64_t bit2uint64(char *bitstr) { char c0; uint64_t i = 0; while(c0 = *(bitstr++)) { i <<= 1; if (c0 == '1') i++; } return i; } /* === main */ int main(int argc, char *argv[] ) { union ufloat uf; union udouble ud; uint8_t *s; int i; char *bitstr, *sign_s , *sign_b , *expo_b, *mantissa_b ; int16_t expo; uint64_t mantissa; if (argc != 2) { usage( argv[0] ); return(-1); } if ((uf.f = ud.f = atof(argv[1])) == 0) { show_error((stderr,"値の解析に失敗しました:%s\n", argv[1])); return(-1); } /* basic */ printf(formatstr_basic , argv[1] , uf.f , ud.f); puts(str_separator); /* float */ s = (uint8_t*)malloc( sizeof(uint8_t) * float_size); parse_float(&s , uf.i); bitstr = alloc_bitstr(s, float_size); sign_b = alloc_bitstr(s, 1); sign_s = (sign_b[0] == '1') ? "-1" : "+1"; expo_b = alloc_bitstr(s + 1, 8); expo = bit2uint16(expo_b) - 127; mantissa_b = alloc_bitstr(s + 9, 23); mantissa = bit2uint64(mantissa_b); printf( formatstr_float , uf.f, bitstr, sign_s, sign_b , expo, expo_b , mantissa, mantissa_b , uf.f , sign_s , mantissa, expo ); puts(str_separator); free(s); free(bitstr); free(sign_b); free(expo_b); free(mantissa_b); /* double */ s = (uint8_t*)malloc( sizeof(uint8_t) * double_size); parse_double(&s , ud.i); bitstr = alloc_bitstr(s, double_size); sign_b = alloc_bitstr(s, 1); sign_s = (sign_b[0] == '1') ? "-1" : "+1"; expo_b = alloc_bitstr(s + 1, 11); expo = bit2uint16(expo_b) - 1023; mantissa_b = alloc_bitstr(s + 12, 52); mantissa = bit2uint64(mantissa_b); printf( formatstr_double , ud.f, bitstr, sign_s, sign_b , expo, expo_b , mantissa, mantissa_b , ud.f , sign_s , mantissa, expo ); puts(str_separator); free(s); free(bitstr); free(sign_b); free(expo_b); free(mantissa_b); return 0; }
トラックバック - http://d.hatena.ne.jp/k_yamamot/20110309/1299682633
リンク元
- 19 http://anond.hatelabo.jp/20081220025833
- 19 http://www.google.co.jp/search?sourceid=chrome&ie=UTF-8&q=cakephp+モバゲー
- 12 http://life.co-hey.com/2010/09/mysql複合indexの威力/
- 11 http://dsas.blog.klab.org/archives/50860867.html
- 11 http://www.google.co.jp/search?q=CakePHP+JSON&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja:official&hl=ja&client=firefox-a
- 8 http://www.google.co.jp/search?hl=ja&client=firefox-a&rls=org.mozilla:ja:official&q=mysql+レプリケーション+停止せず&aq=f&aqi=&aql=&oq=
- 8 http://www.google.co.jp/search?sourceid=chrome&ie=UTF-8&q=mysql+複合インデックス+効率
- 8 http://www.google.co.jp/search?sourceid=navclient&hl=ja&ie=UTF-8&rlz=1T4GGLL_jaJP374JP374&q=絵文字+文字コード 判定
- 6 http://www.google.co.jp/search?q=テーブルを分割 MySQL パーティショニング&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja:official&hl=
- 6 http://www.google.co.jp/search?q=MobileEmoji&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:ja:official&hl=ja&client=firefox-a