2012-04-15 39 views
13

タイトルはかなりわかりやすく、入力は倍の値が与えられています。最も近い次の/前の倍の値を見つける方法(与えられた数値に対してnumeric_limits ::εを見つける方法)

+0

'ダブル次回=値+のstd :: numeric_limitsの ::イプシロン()work'でしょうか?または私は何かを逃している? – rve

+2

@rve:ある時点では、値の増加が停止します(効果はありません)。これは、最初に入力した値が正確に保存されない新しい値に近似しているためです。だから、あなたは次の数字に達していないというループで立ち往生してしまいます。 – GManNickG

+0

@rve、いいえ、値1の倍数のイプシロンであるため、イプシロンはより大きい数値で大きくなります。http://en.wikipedia.org/wiki/Double-precision_floating-point_format – kovarex

答えて

19

あなたのコンパイラはC99の数学関数/ C++ 11を実装している場合、あなたはnextafterを使用することができます。

#include <cfloat> // DBL_MAX 
#include <cmath> // std::nextafter 

double x = 0.1; 

// next representable number after x in the direction of DBL_MAX 
double xPlusSmallest = std::nextafter(x, DBL_MAX); 

あなたのコンパイラは、おそらく、それをそれをサポートしていない場合でも、それには本質的なものがあります。あなたのコンパイラがそれをサポートしていない場合

を(。。MSVCは、GCCは、おそらく標準としてそれを実装して、たとえば、2005年から_nextafterがあった)が、ブーストは、あなたがこれを行うことができ、あなたに提供されています:

#include <boost/math/special_functions/next.hpp> // boost::float_next 

double x = 0.1; 

// next representable number after x 
double xPlusSmallest = boost::math::float_next(x); 

この(エミュレートC99)に相当する:

#include <boost/math/special_functions/next.hpp> // boost::nextafter 
#include <cfloat> // DBL_MAX 

double x = 0.1; 

// next representable number after x in the direction of DBL_MAX 
double xPlusSmallest = boost::math::nextafter(x, DBL_MAX); 

そして、あなたのためにそれらの作品のどれも、あなたはそれをオープンブーストヘッダをクラックしてコピーする必要がないだろう場合。

+0

素敵な答えをありがとう、ブーストを使用して私はそれの方法を使用します。 – kovarex

-4
#define FLT_MIN   1.175494351e-38F  /* min positive value */ 
#define FLT_MAX   3.402823466e+38F  /* max value */ 
#define DBL_MIN   2.2250738585072014e-308 /* min positive value */ 
#define DBL_MAX   1.7976931348623158e+308 /* max value */ 

http://xona.com/2006/07/26.html

+1

OPが望んでいると思います最小/最大値ではなく、2つの浮動小数点数の間に可能な最小の差*を知ることができます。 –

+0

でも最小値がfloat.hファイル –

+0

@AlexZKに格納されている値よりも小さい値を示しています。それはFPUによって異なります。私が与えたリンクは、FPUが処理できる精度を示しています。そして、私は最小の違いが処理できる最小の正の値になると感じます。 –

7

あなたのプラットフォームがIEEE754 floatを使用している場合にのみ実際には有効ではない非常に汚いトリックです:floatのバイナリ表現はfloat値と同じ方法で順序付けられているため、バイナリ表現を増やすことができます:

double x = 1.25; 

uint64_t * const p = reinterpret_cast<uint64_t*>(&x); 

++*p; // undefined behaviour! but it gets the next value 

// now x has the next value 

あなたは適切なuint64_t値を得るために、通常のバイナリコピーの体操をすることによって、完全に合法的に同じ効果を得ることができます。ゼロ、無限大、NaNも正しくチェックしてください。

+0

GCCは型間の 'memcpy'をできるだけエイリアスに置き換えてくれると聞いてきましたが、それは単なる神話かもしれません。 – GManNickG

+0

これは正しく仮数のオーバーフローを処理しますか?バイナリ表現が.111111111 * 2^kの場合はどうなりますか? .00000000 * 2^{k + 1}か? –

+0

@Alexandre C:はい、そうです。 – user763305

-2

方法について:

x += fabs(x) * std::numeric_limits<double>::epsilon(); 
+0

タイプごとに掛け算しますか? – GManNickG

+0

あなたが ':: min()'を追加することを意図していたとすれば、これは非正規化数に対しては機能せず、通常の場合の証明が必要です。 IEEE 754は、乗算と加算の下でULPについて何を保証しますか?私は '1.5 * 2^n≦x <2^n + 1 'という数値は乗算後に希望のイプシロンの倍になると考えていますが、これは融合積和演算で動作するはずです。 – Potatoswatter

+0

おっと - ipsilonを書くのを忘れた... –

関連する問題