転送に 16 ビットのデータ値が必要な iPhone からスレーブ デバイスにデータを転送しています。転送する必要がある浮動小数点値がありますが、その大きさと 16 進数での表現方法を知るにはどうすればよいでしょうか?
下位ニブルと上位ニブルを切り替える必要がある場合があるため、16 進表現が必要です。
転送に 16 ビットのデータ値が必要な iPhone からスレーブ デバイスにデータを転送しています。転送する必要がある浮動小数点値がありますが、その大きさと 16 進数での表現方法を知るにはどうすればよいでしょうか?
下位ニブルと上位ニブルを切り替える必要がある場合があるため、16 進表現が必要です。
詳細を知りたい場合は、Web でIEEE 浮動小数点規格を調べてください。しかし、それを 16 進数で表すには、数値を生成し、個々のバイトを取得して、それらの 16 進数表現を生成するだけです。知っておく必要がある 2 つのことは、値の長さ (例: sizeof(double)
) と、「ビッグ エンディアン」または「リトル エンディアン」のどちらで格納されているかです。iOS デバイスは常に「リトル エンディアン」です。つまり、値の最下位バイトが最小のメモリ アドレスになります。
バイトを取得する簡単な方法は、 または の C と の適切な長さの配列を作成union
するfloat
ことdouble
ですunsigned char
。unsigned char
浮動小数点値をユニオンに格納してから、バイトを取得して 16 進数に変換します。この「エイリアシング」を実行するために、適切なポインター型のキャストを使用することもできます。
union {
float f;
double d;
unsigned char c[8];
} foo;
foo.d = 3.14156;
for(int i=0;i<8;i++) printf("%02X",foo.c[i]);
ユニオンとエイリアシングがオプションではないJava ユーザーの場合、Float と Double には次のクラス メソッドがあります。
Float.floatToRawIntBits(floatValue)
Double.doubleToRawLongBits(doubleValue)
そしてそれらの逆
Float.intBitsToDouble(intValue)
Double.longBitsToDouble(longValue)
これらはキャストのような変換を行わないことに注意してください(たとえば、4.1 float は4 int に変換されません)。代わりに、ビット パターンを変更せずに float から整数形式に転送します。
iOS デバイスでは、浮動小数点数は、符号ビット、バイアスされた指数、およびエンコードされた仮数と共に格納されます。
32 ビット浮動小数点 ( float
) では、指数は 8 ビットで、127 でバイアスされ、エンコードされた仮数は 23 ビットです。64 ビット float ( double
) では、指数は 11 ビットで、1023 でバイアスされ、エンコードされた仮数は 52 ビットです。
次に、32 ビット浮動小数点数について説明します。それは記憶からです。私はそれを再確認していません。64 ビット float も同様です。
フロート F を考えます。 E を で定義しunsigned int E = (union { float f; unsigned int u; }) { F }.u;
ます。iOS デバイス (および他の多くの一般的なコンピューター) では、E には F のエンコード、つまりそれを表すビットが含まれます。
ありましょうE>>31
。サインビットです。F が正 (+0 を含む) の場合は 0、F が負 (-0 を含む) の場合は 1 です。
e とするE>>23 & 0xff
。それが偏った指数です。偏りのない (実際の) 指数は e-127 です。
f とするE & 0x7fffff
。それが符号化された仮数です。0 < e < 255 の場合、実際の仮数は 1. f 2です。ここで、fは f の 23 ビットを 2 進数で表したものです。したがって、f が 0x600000 の場合、f は 2 進数で 110000000000000000000 2であるため、実際の有意桁は 1.1100000000000000000000 2であり、1.11 2であり、1+1/2+1/4 = 1.75 です。
全体として、このエンコーディングで表される数値は (-1) s •2 e-127 •1 です。f2._ したがって、エンコーディング 0x40600000 の場合、s は 0、e は 0x100 = 128、f は 110000000000000000000 2であるため、値は (-1) 0 •2 128-127 •1.75 = 1•2•1.75 = 3.5 です。
いくつかの特殊なケースがあります。e が 0 の場合、実際の仮数は 1.f 2ではなく0.f 2です。つまり、暗黙の 1 は 0 に変更されます。f がゼロの場合、表現される値は 0 であることに注意してください。符号は浮動小数点ゼロでも意味があります。+0 と -0 の動作はわずかに異なります。
e が 255 で f が 0 の場合、表される値は符号に応じて +infinity または -infinity の無限大になります。
e が 255 で f が 0 でない場合、値は何らかの実装定義のセマンティクスを持つ NaN です。
浮動小数点値をエンコードするには、符号を決定してから、値の大きさを超えない最大の 2 のべき乗を計算します。この 2 のべき乗は、偏りのない指数になります。次に、その値を 2 の累乗で割り、仮数に収まるように丸めます。これにより、仮数が得られます。丸めによって有効桁数が 2 になる特殊なケース (指数を調整する必要があります) や、指数がアンダーフローするのに十分な大きさであるか、アンダーフローが非正規範囲 (バイアスされた指数が 1 または大きい)。