質問
浮動小数点数の符号を判断する簡単な方法はありますか?
私は実験してこれを思いつきました:
#include <iostream>
int main(int argc, char** argv)
{
union
{
float f;
char c[4];
};
f = -0.0f;
std::cout << (c[3] & 0x10000000) << "\n";
std::cin.ignore();
std::cin.get();
return 0;
}
ここで (c[3] & 0x10000000) は負の数の値 > 0 を与えますが、これには次のような仮定を行う必要があると思います。
- マシンのバイトサイズは 8 ビットです
- 浮動小数点数は 4 バイトの大きさですか?
- マシンの最も重要なビットは、左端のビットです(エンディアンネス?)
これらの仮定が間違っている場合、または見逃している場合は修正してください。
解決
が有効な浮動小数点数だと仮定すると(としない、例えば、NaNで):
float f;
bool is_negative = f < 0;
はそれは浮動小数点数が正であるか否かを試験する方法を理解するために読者の課題として残されている。
他のヒント
試してみてください
float s = copysign(1, f);
<math.h>
から
それはあなたのシステム/コンパイラで利用できる場合は、別の有用なものは、<ieee754.h>
を#includingすることができる。
使用signbit()のmath.hから。
1)はsizeof(int)が、それとは何の関係もありません。
2)はい、CHAR_BIT == 8を仮定します。
それはよりよい宣言組合へとなりますので、我々は確認する必要があるビットは、少しのための大きなエンディアンのためc[0]&0x80
、またはc[3]&0x80
あるので、 3)私たちはそのためにMSBが必要ですが、エンディアンだけのバイト順序に影響はなく、順序ビットuint32_t
とは0x80000000に確認ます。
このトリックは唯一の非特殊なメモリオペランドの感覚を持っています。 XMMかのx87レジスタであるfloat
値にそれを行うことは直接的なアプローチよりも遅くなります。また、NaNまたはINFのような特別な値を扱いません。
あなたのシステムのための浮動小数点形式をグーグル。多くの使用IEEE 754及び検証するデータ内の特定の符号ビットがあります。図1は、負0が正です。他のフォーマットは類似して、調べやすいようなものを持っています。
正確にあなたが= -0.0F Fのようにハードコードされた割り当てにしたい番号を与えるために、コンパイラを取得しようとしている。注;動作しない場合があります。浮動小数点形式とは何の関係もありませんが、パーサとコンパイラが使用するC / C ++ライブラリに関係しています。マイナスゼロを生成すること、または一般にその些細であってもなくてもよい。
私はのhttpからこれを持っている:// WWW。 cs.uaf.edu/2008/fall/cs441/lecture/10_07_float.htmlする これを試してください:
/* IEEE floating-point number's bits: sign exponent mantissa */
struct float_bits {
unsigned int fraction:23; /**< Value is binary 1.fraction ("mantissa") */
unsigned int exp:8; /**< Value is 2^(exp-127) */
unsigned int sign:1; /**< 0 for positive, 1 for negative */
};
/* A union is a struct where all the fields *overlap* each other */
union float_dissector {
float f;
struct float_bits b;
};
int main() {
union float_dissector s;
s.f = 16;
printf("float %f sign %u exp %d fraction %u",s.f, s.b.sign,((int)s.b.exp - 127),s.b.fraction);
return 0;
}
この後半、私に来ては、別のアプローチを考えています。
は、あなたのシステムを知っている場合はIEEE754浮動小数点形式を使用しますが、ありませんどのように大きな浮動小数点型は整数型に関連している、あなたはこのような何かを行うことができます:
bool isFloatIEEE754Negative(float f)
{
float d = f;
if (sizeof(float)==sizeof(unsigned short int)) {
return (*(unsigned short int *)(&d) >> (sizeof(unsigned short int)*CHAR_BIT - 1) == 1);
}
else if (sizeof(float)==sizeof(unsigned int)) {
return (*(unsigned int *)(&d) >> (sizeof(unsigned int)*CHAR_BIT - 1) == 1);
}
else if (sizeof(float)==sizeof(unsigned long)) {
return (*(unsigned long *)(&d) >> (sizeof(unsigned long)*CHAR_BIT - 1) == 1);
}
else if (sizeof(float)==sizeof(unsigned char)) {
return (*(unsigned char *)(&d) >> (sizeof(unsigned char)*CHAR_BIT - 1) == 1);
}
else if (sizeof(float)==sizeof(unsigned long long)) {
return (*(unsigned long long *)(&d) >> (sizeof(unsigned long long)*CHAR_BIT - 1) == 1);
}
return false; // Should never get here if you've covered all the potential types!
}
基本的に、あなたはその後、符号なし整数型、存在のうち、すべての右シフトが、ビットの1つ(符号ビット)として、あなたのフロートのバイト扱います。 「>>」は、このバイパスようにかかわらず、エンディアンの作品という問題ます。
それは符号なし整数型は、浮動小数点型と同じ長さである事前実行を決定することが可能なら、あなたはこれを省略することができます:
#define FLOAT_EQUIV_AS_UINT unsigned int // or whatever it is
bool isFloatIEEE754Negative(float f)
{
float d = f;
return (*(FLOAT_EQUIV_AS_UINT *)(&d) >> (sizeof(FLOAT_EQUIV_AS_UINT)*CHAR_BIT - 1) == 1);
}
これは私のテスト・システム上で働いていました。誰もが任意の警告を参照するか、または「落とし穴」を見落とし?
なぜだめですか if (f < 0.0)
?