IEEE754は、 浮動小数点数の計算で最も広く採用されている標準規格で、通信電文においてIEEE754の規格に沿ったデータが送られてくる場合が見られます。
IEEE754は単精度(32bit)と倍精度(64bit)がありますが考え方は同様です。ここでは単精度について記載してみたいと思います。
例えば電文で16進数での 0x3F 0x56 0x27 0x78 が送られてきたとします。これをEXCELで理解していきたいと思います。表示しているEXCELファイルはこちらからダウンロード可能です。
※ 本EXCELファイルはご自由にご使用いただけますが、ご使用にあたっての一切の事象について当社では責任を負いかねます。お客様の責任においてご使用ください。
STEP1として2進数で表すと次のようになります。EXCELでのHEX2BIN関数を用います。
STEP2として、STEP1の結果をLEFT/RIGHT関数を用いて、符号部・指数部・仮数部に分けます。
符号部はIF関数、指数部は BIN2DEC関数で10進数として127を減算 します。
STEP4で仮数部の先頭に1を加え、RIGHT関数と文字列結合(&)を用いて結合し、それをMID関数を用いて、24桁の0/1をそれぞれのセル(VAL)に記載します。それぞれに左から順に1~24(ID)を割り振り、=VAL*2^(1-ID)の演算を行い、その結果をSUM関数で合計値をだします。
SETEP5として、符号部×仮数部×2^指数部で計算で計算し、結果0.8365397が得られます。
さて実際に電文を受けた場合、これら計算において自分自身で関数を作って演算するのは手間ですがArudinoIDE(確認していませんがC/C++環境で動作すると思います)ではUNIONを使用すれば、そのまま演算してくれます。setup()部分に次のように記載してみます。
typedef union { float val; byte ary[4]; int i; } Ta; Ta a; byte test[4]; test[0] = 0x3F; test[1] = 0x56; test[2] = 0x27; test[3] = 0x78; //! UNION構造体に反対方向に代入する… a.ary[0] = test[3]; a.ary[1] = test[2]; a.ary[2] = test[1]; a.ary[3] = test[0]; //! 変換結果… printf( "%f ( %08X )\n", a.val, a.i ); //! ビットの列を表示します for (int i = 31; i >= 0; i-- ) { printf( "%d", ( a.i >> i ) & 1 ); } printf( "\n" ); //! 指数部( 1ビット )、指数部( 8ビット )、仮数部( 23ビット )を取り出します printf( "符号部 : %X\n", ( a.i >> 31 ) & 1 ); printf( "指数部 : %X\n", ( a.i >> 23 ) & 0xFF ); printf( "仮数部 : %X\n", a.i & 0x7FFFFF );
実行結果は次の通り。
0.836540 ( 3F562778 ) 00111111010101100010011101111000 符号部 : 0 指数部 : 7E 仮数部 : 562778