C / C ++の最小double値


92

C(++)プログラムで最小の負の値を表す(たとえば、負の無限大を使用する)ための標準的および/または移植可能な方法はありますか?

float.hのDBL_MINは、最小の正の数です。


4
私は-DBL_MAXのために行くだろうが、これはそうではない、なぜ私は確か:-)いくつかの技術的な理由があるんだ

4
@ニール、ありません、それは2の補数整数のようではありません
fortran 2009

浮動小数点型の範囲がゼロを中心に対称でなければならないと言うことは、標準ではまだ何も見ていません。しかし、limits.hと<limits>の定数は、CとC ++の両方の標準がそうなることを期待していることを示唆しています。
Steve Jessop

4
実際、float.hのDBL_MINは、最小の正の 正規化された数値です。さらに小さい数があります。
fdermishin 2013年

1
@fortran:IEEE 754 FPは符号ビットを使用し、確かに最近のほとんどのFPハードウェアはIEEE754です。しかしCとC ++は非IEEE754 FPハードウェアをサポートしているため、言語が-DBL_MAXを保証するかどうかについては疑問が残ります。表現可能な最小値と等しくなければなりません。
j_random_hacker 2013

回答:


134

-DBL_MAX ANSI Cでfloat.hの中で定義されています、。


これは最も標準的なポータブルらしい
ウィル

これが私の-1の説明です:-DBL_MAXは、表現可能な最小値は言うまでもなく、CまたはC ++言語によって表現可能であることが保証されていると誰が言いますか?ほとんどのFPハードウェアがIEEE754に準拠しており、この表現を使用しているという事実は、-DBL_MAXが標準に準拠したCプラットフォームで動作することが保証されていることを意味するものではありません。
j_random_hacker 2013

@j_random_hacker:以下のFortranの回答を参照してください。
JohnTortugo 2014年

3
@j_random_hackerこれは非常に良い点ですが、C標準は-DBL_MAX正確に表現可能である必要があるため、FPハードウェアがそれを実行できない場合、実装はそれを回避する必要があります。C99の5.2.4.2.2浮動小数点型<float.h> p2特性の浮動小数点モデルを参照してください(それ以降、他の場所に移動された可能性があります)。

2
@j_random_hackerはい。ただし、p2はe_minとe_maxが符号ビットから独立していることを指定しているためDBL_MAX、正確に(1 − b ^ −p)b ^ e_maxであり、正確に表現できます。最も負の有限値は正確に-(1 − b ^ −p)b ^ e_maxであり、これはたまたま正確であるため-DBL_MAX、否定DBL_MAXしても丸め誤差は発生しません。

70

浮動小数点数(IEEE 754)は対称であるため、最大値(DBL_MAXまたはnumeric_limits<double>::max())を表すことができる場合は、マイナス記号を前に付けるだけです。

そして、それはクールな方法です:

double f;
(*((long long*)&f))= ~(1LL<<52);

6
+1浮動小数点数の対称性を指摘するため:)
Andrew Hare

4
IEEE754フロートを使用しないC / C ++実装はどうですか?
Steve Jessop

1
-ffast-mathのgccのマニュアルには、「-fno-math-errno、-funsafe-math-optimizations、-ffinite-math-only、-fno-rounding-math、-fno-signaling-nans、および-fcx-limited-を設定します。 rangeこのオプションは、数学関数のIEEEまたはISOルール/仕様の正確な実装に依存するプログラムの出力が正しくなくなる可能性があるため、-Oオプションではオンになりません。ただし、これを行うプログラムのコードは高速になる可能性があります。これらの仕様の保証は必要ありません。」高速演算は一般的な設定であり、たとえばIntelICCはデフォルトで設定されています。すべてのすべてではなく、必ず何私にとって、これは手段:-)
ウィル

4
これは、実装がIEEE 754演算を使用しないことを意味しますが、公平を期すために、これらのオプションは依然としてIEEE表現を使用します。すべてのプロセッサがネイティブのfloat形式を持っているわけではないため、IEEE以外の表現を使用するエミュレーションライブラリが見つかる場合があります(ただし、製造元が提供するエミュレーションライブラリに対応する形式を含むC ABIを公開する場合があります)。したがって、すべてのコンパイラが1つを使用できるわけではありません。「標準および/またはポータブル」を求めるときの意味によって異なりますが、原則としてポータブルと実際にはポータブルがあります。
Steve Jessop

3
あなたの言うことはIEEE754にも当てはまりますが、標準ではこのエンコーディングの使用は要求されていません(@SteveJessopが指摘しているように、実際のポータブルは原則としてポータブルと同じではありません)。
クリストフ

44

Cでは、

#include <float.h>

const double lowest_double = -DBL_MAX;

C ++ pre-11では、

#include <limits>

const double lowest_double = -std::numeric_limits<double>::max();

C ++ 11以降では、

#include <limits>

constexpr double lowest_double = std::numeric_limits<double>::lowest();

min()C ++ 11より前の機能はありませんでしたか?それとも、それはとは異なる値-max()ですか?en.cppreference.com/w/cpp/types/numeric_limits
Alexis Wilke

5
@Alexis:リンクしたページの表の一番下の3行を見るとmin、正の値が最小でlowest、負の値が最大であることがわかります。はい、それはひどいです。C ++標準ライブラリの素晴らしい世界へようこそ:-P
rubenvb 2014年

Cの場合、で定義され float.hます。limits.h整数のためである
シプリアンTomoiagă

33

これを試して:

-1 * numeric_limits<double>::max()

参照: numeric_limits

このクラスは、基本的な型ごとに特化されており、そのメンバーは、コンパイルする特定のプラットフォームで型が持つプロパティを定義するさまざまな値を返すか、異なる値に設定されます。


1
なぜだけではないの-numeric_limits<double>::max()ですか?
k06a 2016年

4
@ k06aは、このような長い式で1文字で否定が表され、文字列に「最大」とさえ書かれている場合、遅かれ早かれ誰かを獲得するはずです。記述変数に格納されるか-1 * ...、少し明確にするために使用します。
フィリップハグルンド2017年

20

実無限または最小有限値をお探しですか?前者の場合は、

-numeric_limits<double>::infinity()

これは次の場合にのみ機能します

numeric_limits<double>::has_infinity

それ以外の場合は、

numeric_limits<double>::lowest()

これはC ++ 11で導入されました。

lowest()利用できない場合は、にフォールバックできます

-numeric_limits<double>::max()

これはlowest()原則とは異なる場合がありますが、通常は実際には異なります。


有限値と無限値の差に+1!ただし、この標準は対称浮動小数点エンコーディングを保証していません。したがって-numeric_limits<double>::max()、実際に機能したとしても、理論的には完全に移植可能ではありません。
クリストフ

@Christophe:[x]修正済み
Christoph

10

真にポータブルなC ++ソリューション

C ++ 11以降、を使用できます numeric_limits<double>::lowest()。標準によると、それはあなたが探しているものを正確に返します:

他の有限値yがないような有限値x y < x。ここで。
のすべての専門分野にとって意味がありis_bounded != falseます。

オンラインデモ


移植性のないC ++の答えがたくさんあります!

に行く多くの答えがあります-std::numeric_limits<double>::max()

幸いなことに、ほとんどの場合にうまく機能します。浮動小数点エンコード方式は、仮数と指数の数値を分解し、それらのほとんど(たとえば、一般的なIEEE-754)は、仮数に属さない別個の符号ビットを使用します。これにより、符号を反転するだけで、最大の正を最小の負に変換できます。

ここに画像の説明を入力してください

なぜこれらはポータブルではないのですか?

この標準は、浮動小数点標準を課していません。

私の議論は少し理論的であることに同意しますが、一部のエキセントリックなコンパイラメーカーが、2の補数のいくつかのバリエーションで仮数をエンコードした革新的なエンコードスキームを使用するとします。2の補数エンコーディングは対称ではありません。たとえば、符号付き8ビット文字の場合、正の最大値は127ですが、負の最小値は-128です。したがって、いくつかの浮動小数点エンコーディングが同様の非対称動作を示すことを想像できます。

私はそのようなエンコード方式を知りませんが、要点は、標準では符号反転が意図した結果をもたらすことを保証していないということです。したがって、この人気のある回答(申し訳ありませんが!)は、完全にポータブルな標準ソリューションとは見なされません!/ *少なくともそれnumeric_limits<double>::is_iec559が真実であると主張しなかった場合はそうではありません* /



1

元の質問は無限大に関するものです。だから、使ってみませんか

#define Infinity  ((double)(42 / 0.0))

IEEEの定義によると?もちろん、それを否定することができます。


良いアイデア !そしてそれは動作します。ただし、次の場合に限りますnumeric_limits<double>::has_infinity && ! numeric_limits<double>::traps
クリストフ

1

C(++)プログラムで最小の負の値を表す(たとえば、負の無限大を使用する)ための標準的および/または移植可能な方法はありますか?

Cアプローチ。

多くの実装は+/-無限大をサポートしているため、最も負のdouble値は-INFINITYです。

#include <math.h>
double most_negative = -INFINITY;

標準および/またはポータブルな方法はありますか....?

次に、他のケースも考慮する必要があります。

  • 無限大はありません

単に-DBL_MAX

  • 符号なしの無限大のみ。

この場合、OPが好むと思い-DBL_MAXます。

  • の大きさがDBL_MAX。よりも大きい非正規値。

これは珍しいケースであり、おそらくOPの懸念の範囲外です。doubleが目的の範囲/歳差運動を達成するために浮動小数点のペアとしてエンコードされる場合(double-doubleを参照)、最大の法線 doubleとおそらくより大きな非法線が存在します。私は、両方の最大のもののうちDBL_MAX、最大の法線を参照する必要があるかどうかについての議論を見てきました。

幸い、このペアのアプローチには通常-無限大が含まれているため、最も負の値が残り-INFINITYます。


移植性を高めるために、コードはルートをたどることができます

// HUGE_VAL is designed to be infinity or DBL_MAX (when infinites are not implemented)
// .. yet is problematic with unsigned infinity.
double most_negative1 = -HUGE_VAL;  

// Fairly portable, unless system does not understand "INF"
double most_negative2 = strtod("-INF", (char **) NULL);

// Pragmatic
double most_negative3 = strtod("-1.0e999999999", (char **) NULL);

// Somewhat time-consuming
double most_negative4 = pow(-DBL_MAX, 0xFFFF /* odd value */);

// My suggestion
double most_negative5 = (-DBL_MAX)*DBL_MAX;

-1

float例外を有効にしていない場合(これは私見すべきではありません)、次のように簡単に言うことができます。

double neg_inf = -1/0.0;

これにより、負の無限大が生成されます。フロートが必要な場合は、結果をキャストすることができます

float neg_inf = (float)-1/0.0;

または単精度演算を使用します

float neg_inf = -1.0f/0.0f;

結果は常に同じであり、単精度と倍精度の両方で負の無限大の表現が1つだけあり、期待どおりに相互に変換されます。


なぜあなただけ書くのではなく、これを行うだろう-INFINITY
MM

また、無限大は存在する場合と存在しない場合があり、存在する場合は、正と負を区別できない場合があります(標準C)。
MM

多くのコンパイラやアーキテクチャでは、C / C ++コードによって、無限大値とNaN値の伝播が遅くなります。
markgalassi

@markgalassi詳しく見てください。定数値にneg_inf初期化されていることがわかります。コンパイラがinf値の計算を処理します。また、最大値を計算するためのnull値として使用する場合、通常、最初の反復でより大きな値で上書きされます。つまり、パフォーマンスはほとんど問題になりません。そして、OPは特に「負の無限大を使用する」ことについて-inf質問し、これに対する唯一の正解です。あなたは正解と有用な答えに反対票を投じました。
cmaster -モニカ復活
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.