在C++中,float占4個位元組,double占8個位元組,均采用 IEEE 754 浮點標準;內部都是以二進制為基礎,表述實數,有些實數可以被精確表述,比如0.2,但有些不行,比如0.3,針對這一點,前不久有篇專門的文章介紹這個:浮點運算為什么不準?有人為0.30000000000000004建了個網站
IEEE 754浮點標準
IEEE標準包含一組實數的二進制表示,一個浮點數字包含三個部分:符號(+或者-)、尾數(包含一串有效數位)和一個指數,這些部分都在一個計算機字里,常用的浮點數精度有:單精度(C++內的float型別)、雙精度(C++內的double型別),分配的數位分別是32、64,這些數位被分成如下不同的部分:
| 精度 | 符號 | 指數 | 尾數 |
|---|---|---|---|
| float | 1 | 8 | 23 |
| double | 1 | 11 | 52 |
以雙精度浮點數為例,每個浮點數字被分配了8位元組,或者64位,來存盤對應的三個部分,每個字都具有如下的形式
\[se_1e_2...e_{11}b_1b_2...b_{52} \]其中第一位保存了符號位,后面11位用于保存指數,再后面小數點后的52位保存尾數,符號位是0表示正數,1表示負數,11位的指數表示的正二進制整數,這些正數通過往指數上疊加 \(2^{10}-1=1023\) 得到,指數范圍在-1022和1023之間,e1...e11覆寫了從1到2046之間對應的指數,由于特殊目的,這里沒有使用0和2047,
機器精度
機器精度對應的數字,是1和比1大的最小浮點數之間的距離,對于IEEE雙精度浮點表示,該值為 \(2^{-52}\),對應 float.h 檔案內宏 DBL_EPSILON 的值,
最小的可表達雙精度數字
\(2^{-52}*2^{-1022}\) 是最小的可表達雙精度數字,最小可表達數字和機器精度之間的差別是在于,許多在機器精度以下的數字都是機器可表達的數字,盡管將這些數字加到1上可能沒有什么影響,另一方面,在最小可表達數字以下的雙精度數字完全不能被表示,
boost multiprecision
為了能夠表述更高精度的浮點數,就得向庫方向查找了,gmp, mpfr 可以表述無限精度,但編譯只能gcc吧,boost在1.56版時開始提供 boost.multiprecision 用于支持更高精度數值表述,許可證較其他庫寬松,但在計算效率等方向要遜于gmp, mpfr,
比如采用 bbp 公式(可參考The BBP Algorithm for Pi)計算 pi 的精確結果,代碼如下:
// Author: [email protected]
#include <iostream>
#include <iomanip>
#include <boost/math/constants/constants.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>
// 通過 BBP 公式計算 PI
template <class Type>
Type calc_pi_bbp(int n)
{
Type pi = 0;
std::streamsize prevsize = std::cout.precision(50);
for (int k = 0; k < n; ++k)
{
Type it = static_cast<Type>(1) / pow(16, k)
* (static_cast<Type>(4) / (8 * k + 1)
- static_cast<Type>(2) / (8 * k + 4)
- static_cast<Type>(1) / (8 * k + 5)
- static_cast<Type>(1) / (8 * k + 6));
pi += it;
std::cout << std::left << std::setw(8) << k << pi << std::endl;
}
std::cout.precision(prevsize);
return pi;
}
int main(int argc, char* argv[])
{
std::cout << "Use double: " << std::endl;
calc_pi_bbp<double>(20);
std::cout << std::endl;
std::cout << "Use boost multiprecision: " << std::endl;
calc_pi_bbp<boost::multiprecision::cpp_bin_float_100>(30);
return 0;
}
以double值計算20次結果如下:

再以boost.multiprecision計算30次結果如下:

明顯使用double計算時,第10次之后就每沒有什么變化了(小于2.2204460492503131e-016 (即DBL_EPSILON)的值與 1.0 相加仍然為1.0),而boost.multiprecision還一直在變化,并且結果可以與Window作業系統中計算器存盤的pi值相同(但小數點之后更多數字,這些準不準確就沒比較了),
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/17732.html
標籤:其他
上一篇:optix之紋理使用
