2017-11-06 5 views
0

で二重の私は、マシンイプシロン、C++の異なるデータ型を使用して1 + e > 1を与える可能な最小数eを計算したかったです。私はlong double行動を説明することはできません、私は期待していたものですマシンイプシロン長いC++

epsilon float: 5.96046447753906250e-008 
epsilon double: 1.11022302462515650e-016 
epsilon long double: -0.000000e+000 

floatdoubleのための、しかし:

は、ここに私のコードです:

#include <cstdio> 

template<typename T> 
T machineeps() { 

    T epsilon = 1; 
    T expression; 

    do { 
    epsilon = epsilon/2; 
    expression = 1 + epsilon; 
    } while(expression > 1); 

    return epsilon; 
} 

int main() { 
    auto epsf = machineeps<float>(); 
    auto epsd = machineeps<double>(); 
    auto epsld = machineeps<long double>(); 

    std::printf("epsilon float: %22.17e\nepsilon double: %22.17e\nepsilon long double: %Le\n", epsf, epsd, epsld); 

    return 0; 
} 

しかし、私はこの奇妙な出力が得られます。

誰かが間違ったことを教えてもらえますか?

+3

これは実際のためのものか、['std :: numeric_limits :: epsilon'](http://en.cppreference。 com/w/cpp/types/numeric_limits/epsilon)? – StoryTeller

+0

再現できません:... ... ipsilon long double:5.421011e-20' –

+0

このコードの動作は環境に設定されている丸めモードに依存しているので、とにかくかなり壊れています。 –

答えて

1

結果を再現できません。私が手:ダブルロング

イプシロン:5.421011e-20

をとにかく、論理的に、コードのようなものでなければなりません:私のプラットフォームで

template<typename T> 
T machineeps() { 
    T epsilon = 1, prev; 
    T expression; 

    do { 

    prev = epsilon; 
    epsilon = epsilon/2; 
    expression = 1 + epsilon; 

    } while (expression > 1); 

    return prev; // <-- `1+prev` yields a result different from one 
} 

それはstd::numeric_limits::epsilonに似た値を生成します:

イプシロンフロート:1.19209289550781250e-07

ダブルイプシロン:ダブルロング2.22044604925031308e-16

イプシロン:1.084202e-19

(大きさの異なる順序に注意してください)

0

ここで起こっていくつかのものがあります。

まず、浮動小数点数の実際の宣言された型にかかわらず、浮動小数点数は可能な限り高い精度で行われることがよくあります。たとえば、floatの算術演算は、Intelハードウェア上では80ビットの精度で行われます(これはJavaが元々これを禁止していたため、すべての浮動小数点演算が型の正確な精度で行われる必要がありました;彼らはすぐにそのルールを放棄した)。浮動小数点計算の結果を格納するのは適切な型に値を切り捨てるが、デフォルトではほとんどのコンパイラがこれを無視する。コンパイラに許可しないように指示できます。そのためのスイッチはコンパイラに依存します。つまり、ここで計算されている結果に頼ることはできません。 1 + epsilonの値がない 1よりも大きいので、戻り値はイプシロンの真値より少なくなるとき

第二に、コードにループが終了します。

第3に、2番目の浮動小数点実装と組み合わせると、いくつかの浮動小数点実装では異常値はありません。指数が表現できる最小値より小さくなると、値は0になります。これは、long doubleの値で表示されます。 IEEE浮動小数点はゼロをあまり急に処理しません。その最小指数に達すると、小さな値が徐々に精度を失います。最小の正規化された値と0の間にかなりの値があります。