web-dev-qa-db-ja.com

floatには負のゼロがありますか? (-0f)

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

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

[編集]フロートを比較して等しいかどうかの安全性についてコメントしないでください!重複する質問のあふれているバケットに追加しようとはしていません。

31
tenfour

規格によれば、負のゼロは存在しますが、正のゼロと同じです。ほとんどすべての目的で、この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

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

18
Rosh Oxymoron

たとえば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を使用した場合と同じ結果になります(デフォルトの丸めモード)。乗算はゼロの符号を保持できますが、前述のように、通常は観測できません。

some数学ライブラリ関数があり、その動作はゼロの符号に応じて変化する可能性があります。例えば:

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

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

10
Stephen Canon

はいゼロに署名できますが、標準では、等しいとしてテストするために正と負のゼロが必要です

7
Martin Beckett

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

  • -1 * 0
  • 0/-1

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

3
rowan194

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

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

2
Mehrdad

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

1

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

1
old_timer

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

0
pixelbeat

この 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になっているように見えても、失敗します。

0
zviadm

フロートを使用して等式比較を行う場合は注意が必要です。バイナリシステムで10進値を表現しようとしていることを忘れないでください。

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

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

0
gcek2