2017-08-27 8 views
3
#include <iostream> 
#include <limits> 

int main() 
{ 
    double d = std::numeric_limits<double>::max(); 
    std::cout << std::to_string(d) << std::endl; 
    std::cout << std::to_string(d - 1) << std::endl; 
} 
 
[[email protected]_host ~]$ g++ test.cpp 
[[email protected]_host ~]$ ./a.out 
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000 

から1を減算することはできませんしないのはなぜ7と第二一端?なぜそれが最大のダブル

+3

浮動小数点表現について学ぶ必要があります。彼らは最後の桁まで正確ではありません。私はWikipediaが始めるには良い場所があると確信しています。 –

+2

これは確かに重複しています。 – Puppy

+0

http:// floating-point-guiを読んでください。de /(そしてそのURLを覚えている) –

答えて

2

C++でのdouble型は、ほ​​とんどの場合、binary64形式のIEE 754に準拠しています。そこで、この答えをベースにします。浮動小数点数(binary32)、ネイティブC++型を持たないbinary16、IEEE 754以外の浮動小数点フォーマットなどの他の浮動小数点フォーマットにも有効です。あなたの二重のは、それが範囲だ、52ビットおよび11の指数の仮数部から構成されている「ダイナミック」である:

指数は大きなの場合:仮数部は後に、その後、全体の数字を表しますが、それはしません仮数部の限界桁数のために、例のために後続2を表すことができます。

指数がの場合、小文字の:小数点以下は2(1/2,1/4など)となり、より正確になります。

質問: IEEE 754で定義されている丸めモードの1つを指定しない場合、デフォルトは「まるで最も近い値への丸め」です。

最大倍精度値で操作すると、それと最後に表現可能な倍精度値の間のギャップが大きくなります。したがって、1.0を引くと、代数的にはが得られますが、ハードウェアでは表現できません(指数には小さすぎます(52ビット目以降の変更に反映される)ので、FPUは最も近い偶数丸めモードに丸めて、 とし、maxDoubleに丸めます。

問題を解決するには、2つのソリューションを使用できます。プログラムによって計算された値の範囲が大きすぎず、計算速度があまり必要でない場合は、固定小数点演算を使用します。または、CPUメーカー(ヘッダファイルにあることが多い)によって与えられたintrisicsを使用して、丸めモードを0に丸めたり丸めたりするように設定します。

ああ、ここに丸めモードの短いリストがあります:操作の兆候に応じて、最も近い偶数に丸め、切り上げ、切り上げ、0に丸めます。

浮動小数点演算が高い値でコードを作成する場合は、数値が∞または-∞に飽和しているかどうか定期的にチェックする必要があります。これは演算を適用できないためです。

+0

C++は、binary2準拠のIEE745であるために 'double'を必要としませんが、これは最も一般的な実装です。 –

+0

編集中!標準では必要ではありませんが、ほぼすべてのCPUがそれらをネイティブサポートしています(一部の組み込みシステムを除く)ので、混乱するのは簡単です。謝罪いたします。 –

+0

関連する質問:https://stackoverflow.com/questions/34294938/does-the-c-standard-specify-anything-on-the-representation-of-floating-point-n –

6

doubleは、表現のためにIEEE 754標準を使用しています。 enter image description here

あなたの番号の値がステップサイズが1よりはるかに大きいほど大きいです:大きな最小限のステップサイズはにつれて、より大きな数が取得するようintとは異なり代わりに1の固定最小限のステップサイズはありませんそれを単純に保つために、それが10であると仮定しましょう。したがって、1を減算しようとすると、値は次の有効な倍数に丸められます。これは前と同じです。

または17976931348623157081452742373170435679807056752584499659891747680315726078002853876058955863276687817154045895351438246423432132688946418276846754670353751698604991057655128207624549009038932894407586850845513394230458323690322294816580855933212334827479782620414472316873817718091929988125040402618412485836 は有効な倍数ではありません。

+0

おそらくグラフは非常に誇張されていますか?実際のカットオフポイントは10^23程度です。 – Puppy

+1

はい正確ではありません。私は問題を単純化しようとしました。 – Crigges