2009-08-26 11 views
6

正規化された浮動小数点数fが与えられると、fの前後の浮動小数点数が次のとなります。正規化された浮動小数点数fの後(前)の次の正規化浮動小数点数は何ですか?

next_normalized(double&){ 
     if mantissa is not all ones 
      maximally denormalize while maintaining equality 
      add 1 to mantissa 
      normalize 
     else 
      check overflow 
      set mantissa to 1 
      add (mantissa size in bits) to exponent. 
     endif 
} 

しかし、ではなく行うこと、それは、浮動小数点演算を行うことができます:私は、仮数と指数を抽出するビットいじると

、?

std::numeric_limits<double>::epsilon() 

として

は1の「近所」の唯一のエラーの違いである - 例えば:

normalized(d+=std::numeric_limits<double>::epsilon()) = d for d large 

それは誤り差よりもエラー率だが、これ私の素朴な直感

(1.+std::numeric_limits<double>::epsilon())*f //should be the next. 

そして

です特に
(1.-std::numeric_limits<double>::epsilon())*f //should be the previous. 

私は3つの質問を持っている誰もが(IEEE754のために)次のいずれか行っている:

1)は、この問題に関するエラー解析を行って?

2)は、任意正規二日間

(1.+std::numeric_limits<double>::epsilon())*d != d ? 

3)は、二重Fをdはない任意正規ダブル数に対する必要性が存在することを証明した)証明(あるいは証明することができるように

d < f < (1.+std::numeric_limits<double>::epsilon())*d ? 

答えて

7

正規化倍数」とはどういう意味かわかりませんが、次はとなります。 double numberは、ほとんどのC標準の数学ライブラリでnextafter() functionで行われます。

+0

が(そのためにあなたに感謝しないで多くの浮動小数点を行います) – pgast

+1

_denormals_ – kibibu

+0

とは逆のことですが、次の番号を返します。たとえそれが非正規化数であったとしてもです。あなたがnextafter(0.0,1.0)を呼び出すと、非正規化されたケースはそれほどまれではありません.0の次の表現可能な数値は非正規化された数値です(DBL_MINが2e-308の場合は4e-324)。したがって、最初の数値がゼロにならない場合、または非正規化された数値は問題にならない場合にのみ、このソリューションを使用してください。 –

3

3)の文はfalseです。 dが2よりわずかに小さい場合、dと(1 + eps)* dの間に正確に1の浮動小数点数があります。

#include <limits> 
#include <iostream> 

int main(int, char**) 
{ 
    using namespace std; 
    double d = 1.875; 
    cout.precision(18); 
    cout << "d = " << d << "\n"; 
    double d2 = (1.+numeric_limits<double>::epsilon())*d; 
    cout << "d2 = " << d2 << "\n"; 
    double f = d + (d2-d)/2; 
    cout << "f = " << f << "\n"; 
} 

理由は、(1 + EPS)は* 1.875 1.875 + 2 * EPSに丸められ1.875 + 1.875 * EPSを等しくすることである:ここでそれを表示するプログラムです。しかし、1と2の間の連続した浮動小数点数の差はepsであるため、1.875と1.875 + 2 * epsの間に1つの浮動小数点数、つまり1.875 + epsがあります。

2)の文が真であると思います。そして、ロバート・カーン氏は本当にあなたの本当の質問に答えました。

+0

良いカウンターの例 - 私はそれを見なかった理由を知らない。 – pgast

+0

とあなたが追加したことがありますが、そのようなdが多くても1つ存在することを実証しました。 – pgast

+0

前任者(前任者(2))にも当てはまり、2の累乗でも真です(1 + eps)*(pred(predそれらはすべて同じ仮数ビットパターンを持っているため、pred(2^i)は2進数で表現されます。 –

5

Robert Cern氏は、Cのnextafter()関数、IEEE754 nextUp()関数、nextDown()関数を必要としています。

あなたには、いくつかの理由ではnextAfterを避けたい場合は、あなたが行うことができます:

double next = x + scalbn(1.0, ilogb(x) - 52); 

これは、2 ^(xの指数 - 52)を追加し、Xに、最後の場所(ULPに正確に一つの単位であります)。

あなたが可能な通常のcmath機能を持っていない場合:

double x = 1.0; 
uint64_t rep; 
assert(sizeof x == sizeof rep); 
memcpy(&rep, &x, sizeof x); 
rep += 1; 
memcpy(&x, &rep, sizeof x); 

これは、浮動小数点値のビット単位-表現に操作することにより、xの仮数に1を追加します。次の値が次のビンアデインにある場合、これは指数部に持ち込まれ、正しい値を返します。負の値で動作させたい場合は、それを微調整する必要があります。

1

以下に述べるように、IEEE-infinityのインテックスIEEE754形式の正の浮動小数点の場合、連結指数と仮数をn-1ビットの符号なし整数として扱う次の高い値を取得します(1を引くと1を引きます)

負の値の場合はその逆です。特に、符号から独立した絶対的な大きさを表すn-1ビット整数を解釈することができる。したがって、負の浮動小数点数fの後に次の浮動小数点数をゼロに近づけるには、負のものを1を引く必要があります。

0

1.0 - ...イプシロンは、1.0の前身ではないので、負のカウンターパートは、まったく動作しない
1.0の前身は、1.0-イプシロン/ 2.0

関連する問題