10

浮動小数点数の符号を判別する簡単な方法はありますか?

私は実験してこれを思いついた:

#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;
}

where (c[3] & 0x10000000) は、負の数に対して値> 0を与えますが、これには次の仮定を行う必要があると思います:

  • マシンのバイトは 8 ビットです
  • 浮動小数点数は 4 バイトですか?
  • マシンの最上位ビットは左端のビットです (エンディアン?)

これらの仮定のいずれかが間違っている場合、または見逃している場合は、修正してください。

4

9 に答える 9

11

math.h の signbit() を使用します。

于 2010-11-20T22:02:43.257 に答える
11

試す

float s = copysign(1, f);

から<math.h>

<ieee754.h>システム/コンパイラで利用できる場合は、 #include が役立つ場合があります。

于 2010-11-20T22:14:17.830 に答える
10

それが有効な浮動小数点数であると仮定します (たとえば NaN ではありません):

float f;
bool is_negative = f < 0;

浮動小数点数が正かどうかをテストする方法を理解することは、読者の課題として残されています。

于 2010-11-20T22:02:21.233 に答える
2

1) sizeof(int) は関係ありません。

2) CHAR_BIT == 8 と仮定すると、はい。

3) そのためには MSB が必要ですが、エンディアンはバイト オーダーにのみ影響し、ビット オーダーには影響しません。そのため、チェックする必要があるビットはc[0]&0x80ビッグ エンディアンかc[3]&0x80リトル エンディアンかということuint32_tです。

このトリックは、特殊でないメモリ オペランドに対してのみ意味があります。XMM または x87 レジスタにあるfloat値に対して実行すると、直接的なアプローチよりも遅くなります。また、NaN や INF などの特殊な値は扱いません。

于 2010-11-20T22:16:36.660 に答える
1

遅くなりましたが、別のアプローチを考えました。

システムが 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!
}

基本的に、float 内のバイトを符号なし整数型として扱い、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);
}

これは私のテストシステムで機能しました。警告や見落とされた「落とし穴」を見た人はいますか?

于 2015-06-19T16:01:09.100 に答える
1

システムの浮動小数点形式をググってください。多くは IEEE 754 を使用しており、調べるデータには特定の符号ビットがあります。1 はマイナス、0 はプラスです。他の形式にも同様のものがあり、簡単に調べることができます。

f = -0.0F; のようなハードコードされた割り当てを使用して、必要な数値をコンパイラに正確に与えようとすることに注意してください。動作しない場合があります。浮動小数点形式とは関係ありませんが、パーサーとコンパイラーが使用する C/C++ ライブラリーとは関係があります。マイナスゼロを生成することは、一般的にそれほど些細なことかもしれませんし、そうでないかもしれません。

于 2010-11-20T22:23:50.360 に答える
0

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;
}
于 2012-06-04T01:05:56.297 に答える
-1

なぜif (f < 0.0)ですか?

于 2010-11-20T22:03:02.540 に答える