タイトルは一目瞭然で、入力には2倍の値が与えられ、可能な限り最小限の量を加算/減算したい.
4 に答える
を使用できますnextafter
。これは、コンパイラが C99 の数学関数 (つまり、C++11 以降) を実装している場合に使用できます。この関数 (およびそのさまざまなオーバーロード) は、次のように記述できます。
double nextafter(double value, double target);
value
可能な限り最小量だけの方向に 移動target
します (通常は float のビット表現を微調整することによって)。value
がすでに にある場合target
、これは何もしません。
target
がこれよりも大きい場合は、可能な限り最小の量だけvalue
増加します。がこれよりも小さいvalue
場合は、可能な限り最小の量だけ減少します。target
value
value
DBL_MAX
一般的な使用法は、またはのいずれかをターゲットとして渡しINFINITY
、最小量を増やします (または、それらを否定して最小量を減らします)。
とのどちらを選択するかは、境界DBL_MAX
でINFINITY
何をしたいかによって異なりますnextafter(DBL_MAX, DBL_MAX) == DBL_MAX
が、nextafter(DBL_MAX, INFINITY) == INFINITY
.
そして、はい、それは悪い名前です。nextafter
およびnexttoward
も参照してください: なぜこの特定のインターフェイス? .
#include <cfloat> // DBL_MAX
#include <cmath> // std::nextafter
double x = 0.1;
// Next representable number **after** x in the direction of DBL_MAX.
// (i.e., this is larger than x, and there is no double between it and x)
double xPlusSmallest = std::nextafter(x, DBL_MAX);
// Next representable number **before** x in the direction of -DBL_MAX.
// (i.e., this is smaller than x, and there is no double between it and x)
double xMinusSmallest = std::nextafter(x, -DBL_MAX);
コンパイラがそれをサポートしていなくても、おそらく組み込み関数があります。_nextafter
(たとえば、MSVC には2005 年からあります。GCC はおそらくそれを標準として実装しています。)
コンパイラがサポートしていなくても Boost を利用できる場合は、次のようにすることができます。
#include <boost/math/special_functions/next.hpp>
#include <cfloat>
double x = 0.1;
double xPlusSmallest = boost::math::nextafter(x, DBL_MAX);
double xMinusSmallest = boost::math::nextafter(x, -DBL_MAX);
これらのいずれもうまくいかない場合は、Boost ヘッダーを開いてコピーするだけです。
これは、実際には合法ではなく、プラットフォームが IEEE754 浮動小数点数を使用している場合にのみ機能する非常に汚いトリックです: 浮動小数点数のバイナリ表現は、浮動小数点値と同じ方法で順序付けられるため、バイナリ表現をインクリメントできます:
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 も適切にチェックしてください。
どうですか:
x += fabs(x) * std::numeric_limits<double>::epsilon();
#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 */