double
型は10進で最大16桁程度の有効桁数しかないと理解していますが、std::setprecision(50)
のようにそれより大きい桁数を設定しても、なんらかの値が出力されます。
例えば、以下のコードで std::log(2)
の値を出力すると、15桁程度までは真の値と合っていて、それ以降も間違ってはいますが、値が出力されます。
そこで質問なのですが、
- 16桁以降の値はどこから来たのでしょうか?
std::setprecision(53)
より大きい値を設定しても53桁までしか表示されないようですが、そういう仕様でしょうか?- もしくは大きい桁数を設定した場合の挙動は動作未定義なのでしょうか?
参考
環境
- C++14
- Visual Studio 2019 / GCC 11 (Wandboxで確認)
- 上記2つのコンパイラで出力結果が一致することを確認
コード
text
10.693147180559945 28622676398299518041312694549560546 出力 20.693147180559945 30941723212145817656807550013436026 正解
正解のソース: log(2) 50digits - Wolfram|Alpha
cpp
1#include <cmath> 2#include <iomanip> 3#include <iostream> 4 5int main() 6{ 7 std::cout << std::log(2.) << std::endl; 8 // 0.693147 9 10 std::cout << std::setprecision(16) << std::log(2.) << std::endl; 11 // 0.6931471805599453 12 13 std::cout << std::setprecision(52) << std::log(2.) << std::endl; 14 // 0.6931471805599452862267639829951804131269454956054688 15 16 std::cout << std::setprecision(53) << std::log(2.) << std::endl; 17 // 0.69314718055994528622676398299518041312694549560546875 18 19 std::cout << std::setprecision(54) << std::log(2.) << std::endl; 20 // 0.69314718055994528622676398299518041312694549560546875 21 22 // 正解 0.69314718055994530941723212145817656807550013436026 23 24 return 0; 25}
追記
std の実装はまだ確認してませんが、yohhoy さん、SHOMI さんのコメントで値がどこから出てきたのか謎が解けました。
ご回答ありがとうございます。
double a = std::log(2.)
の浮動小数点表記
bias = 1023
- 仮数部
0x162E42FEFA39EF * (2 ** -52)
- 指数部
0x3FE
- 浮動小数点数:
0x162E42FEFA39EF * (2 ** -52) * (2**0x3FE - 1023) = 6243314768165359 / 9007199254740992
6243314768165359 / 9007199254740992 = 0.69314718055994528622676398299518041312694549560546875
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/07/26 18:24 編集
2020/07/27 02:03