web-dev-qa-db-ja.com

1.0に最も近い倍数は何ですか、それは1.0ではありませんか?

1.0に最も近いが実際には1.0ではないdoubleをプログラムで取得する方法はありますか?

これを行うための1つのハッキング方法は、doubleを同じサイズの整数にmemcpyしてから1を引くことです。 IEEE754浮動小数点形式の動作方法では、小数部分をすべてゼロ(1.000000000000)からすべて1(1.111111111111)に変更しながら、指数を1ずつ減らします。ただし、整数はリトルエンディアンで保存され、浮動小数点はビッグエンディアンで保存されるマシンが存在するため、常に機能するとは限りません。

87
jorgbrown

CおよびC++では、次は1.0に最も近い値を示します。

#include <limits.h>

double closest_to_1 = 1.0 - DBL_EPSILON/FLT_RADIX;

ただし、C++の以降のバージョンでは、limits.hは廃止され、climitsが採用されました。ただし、とにかくC++固有のコードを使用している場合は、

#include <limits>

typedef std::numeric_limits<double> lim_dbl;
double closest_to_1 = 1.0 - lim_dbl::epsilon()/lim_dbl::radix;

Jarod42が彼の答えで書いているように、C99またはC++ 11以降では、nextafterも使用できます。

#include <math.h>

double closest_to_1 = nextafter(1.0, 0.0);

もちろん、C++では、cmathをインクルードして、std::nextafter代わりに。

22
celtschk

C++ 11以降、 nextafter を使用して、指定された方向で次の表現可能な値を取得できます。

std::nextafter(1., 0.); // 0.99999999999999989
std::nextafter(1., 2.); // 1.0000000000000002

デモ

138
Jarod42

Cでは、これを使用できます。

_#include <float.h>
...
double value = 1.0+DBL_EPSILON;
_

_DBL_EPSILON_は、1と、表現可能な1より大きい最小値との差です。

実際の値を表示するには、数桁で出力する必要があります。

私のプラットフォームでは、printf("%.16lf",1.0+DBL_EPSILON)は_1.0000000000000002_を返します。

25
barak manos

C++では、これも使用できます

1 + std::numeric_limits<double>::epsilon()
4
phuclv