37

IEEE 浮動小数点数には、符号を示すビットが割り当てられています。つまり、技術的には、ゼロの異なるバイナリ表現 (+0 と -0) を使用できます。たとえば、負のゼロの浮動小数点値になる C で実行できる算術演算はありますか?

0.0fこの質問は、を使用して安全に比較できるかどうかを疑問視する別の質問に触発されたものであり、一見完全に等しい値で壊れる==原因となるゼロを表す他の方法があるかどうかさらに疑問に思いました。float1 == 0.0f

[編集] float を等しいかどうか比較することの安全性についてコメントしないでください! 私は重複した質問のあふれんばかりのバケツに追加しようとしているわけではありません。

4

10 に答える 10

30

標準によれば、負のゼロは存在しますが、正のゼロと同じです。ほとんどすべての目的で、この 2 つは同じように動作し、多くの場合、ネガの存在は実装の詳細であると考えられています。ただし、まったく異なる動作をする関数がいくつかあります。つまり、除算とatan2です。

#include <math.h>
#include <stdio.h>

int main() {
    double x = 0.0;
    double y = -0.0;
    printf("%.08f == %.08f: %d\n", x, y, x == y);
    printf("%.08f == %.08f: %d\n", 1 / x, 1 / y, 1 / x == 1 / y);
    printf("%.08f == %.08f: %d\n", atan2(x, y), atan2(y, y), atan2(x, y) == atan2(y, y));
}

このコードの結果は次のとおりです。

0.00000000 == -0.00000000: 1
1.#INF0000 == -1.#INF0000: 0
3.14159265 == -3.14159265: 0

これは、コードが明示的な処理を必要とせずに特定の制限を正しく処理することを意味します。単純な計算エラーが符号を変更し、値が正しくない可能性があるため、制限に近い値に対してこの機能に依存することが良い考えであるかどうかは定かではありませんが、記号を変更します。

于 2011-02-23T19:45:30.117 に答える
16

たとえば、負のゼロの浮動小数点値になる C で実行できる算術演算はありますか?

もちろん:

float negativeZero = -10.0e-30f * 10.0e-30f;

乗算の数学的に正確な結果は浮動小数点値として表現できないため、最も近い表現可能な値に丸められます-0.0f

負のゼロのセマンティクスは、IEEE-754 標準によって明確に定義されています。その動作が算術式のゼロの動作と異なる唯一の実際の観察可能な方法は、それで割ると、無限の異なる符号が得られることです。例えば:

1.f /  0.f --> +infinity
1.f / -0.f --> -infinity

を使用した比較および加算と減算は、 (デフォルトの丸めモードで) を使用した場合-0.fと同じ結果になります。+0.f乗算はゼロの符号を保持できますが、前述のように、通常は観察できません。

ゼロの符号によって動作が異なる数学ライブラリ関数がいくつかあります。例えば:

copysignf(1.0f, 0.0f) -->  1.0f
copysignf(1.0f,-0.0f) --> -1.0f

これは、複雑な関数でより一般的です。

csqrtf(-1.0f + 0.0f*i) --> 0.0f + 1.0f*i
csqrtf(-1.0f - 0.0f*i) --> 0.0f - 1.0f*i

ただし、一般に、負のゼロについて心配する必要はありません。

于 2011-02-23T19:50:22.963 に答える
8

はい、ゼロに署名できますが、標準では、正と負のゼロが等しいかどうかをテストする必要があります

于 2011-02-23T19:28:32.597 に答える
5

負のゼロの答えになる単純な算術演算がいくつかあります (少なくとも、私がテストした i386/x64/ARMv7/ARMv8 システムでは):

  • -1 * 0
  • 0 / -1

算術式を単純化するためのオプティマイザを書いていたとき、これらのことに驚きました。" a = b * 0 " を " a = 0 " に最適化すると、b がたまたま負の場合 (正解は -0)、間違った答え (+0) になります。

于 2016-04-05T09:37:59.043 に答える
2

はい、 floatに負のゼロがありますが、いいえ、浮動小数点値を比較するときにこれについて心配する必要はありません。

浮動小数点演算は、特殊なケースで正しく機能するように定義されています。

于 2011-02-23T19:29:13.083 に答える
1

はい、 s は(IEEE 浮動小数点を使用するシステムで)floatなどの他の IEEE 浮動小数点型と同様に負のゼロを持ちます。doubleそれらを作成する方法の例が Octave にあります同じ操作が C でも機能します。==ただし、演​​算子は +0 と -0 を同じように扱うため、負のゼロはそのタイプの比較を壊しません。

于 2011-02-23T19:28:30.727 に答える
1

はい、+0 と -0 を持つことができますが、それらは異なるビット パターンです (等値テストに失敗するはずです)。== を float で使用しないでください。IEEE float は使用しないでください。< または > は問題ありません。このトピックについては他にも多くの質問や議論があるので、ここでは触れません。

于 2011-02-23T19:33:34.580 に答える
0

-lmには、値が負(-0を含む)であるかどうかを示すために使用できるsignbit()関数があります。

于 2013-02-04T00:04:31.943 に答える
0

これfloat1 == 0.0fは決して安全な比較ではありません。

次のようなものがある場合

float x = 0.0f;
for (int i = 0; i < 10; i++) x += 0.1f;
x -= 1.0f;
assert (x == 0.0f);

一見0であるはずなのに失敗します。

于 2011-02-23T19:29:05.670 に答える
0

float を使用して等値比較を行う場合は注意が必要です。2 進法で 10 進値を表現しようとしていることを思い出してください。

浮動小数点値が 0 に等しいことを確認しても安全ですか?

浮動小数点値を比較する必要がある場合は、許容できる許容範囲を使用するかfloat1 <= toleranceVal && float1 >= toleranceVal2、10 倍して整数としてキャストすることをお勧めします。 if (!(int)(float1 * 10000)) { .. some stuff .. }

于 2011-02-23T19:41:28.407 に答える