浮点运算与boost.multiprecision
在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位,来存储对应的三个部分。每个字都具有如下的形式
\]
其中第一位保存了符号位,后面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: bitbybit3d@163.com
#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值相同(但小数点之后更多数字,这些准不准确就没比较了)。
浮点运算与boost.multiprecision的更多相关文章
- boost之multiprecision
multiprecision boost中提供的高精度库,支持高精度整型,浮点型等.并且提供统一的接口模板,只需要指定对应的后端类型即可实现对应类型的高精度计算: boost::multiprecis ...
- 在Visual Sutdio 2017中使用boost库
在Visual Sutdio 2017中使用boost库 转载 https://blog.csdn.net/u011054333/article/details/78648294 对C++有一 ...
- Awesome C/C++
Awesome C/C++ A curated list of awesome C/C++ frameworks, libraries, resources, and shiny things. In ...
- zz A list of open source C++ libraries
A list of open source C++ libraries < cpp | links http://en.cppreference.com/w/cpp/links/libs Th ...
- awesome cpp
https://github.com/fffaraz/awesome-cpp Awesome C/C++ A curated list of awesome C/C++ frameworks, lib ...
- C/C++ 开源库及示例代码
C/C++ 开源库及示例代码 Table of Contents 说明 1 综合性的库 2 数据结构 & 算法 2.1 容器 2.1.1 标准容器 2.1.2 Lockfree 的容器 2.1 ...
- [转]awsome c++
原文链接 Awesome C++ A curated list of awesome C++ (or C) frameworks, libraries, resources, and shiny th ...
- Boost 1.61.0 Library Documentation
http://www.boost.org/doc/libs/1_61_0/ Boost 1.61.0 Library Documentation Accumulators Framework for ...
- boost库的安装,使用,介绍,库分类
1)首先去官网下载boost源码安装包:http://www.boost.org/ 选择下载对应的boost源码包.本次下载使用的是 boost_1_60_0.tar.gz (2)解压文件:tar - ...
随机推荐
- CodeForces985G Team Players
G. Team Players time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...
- CSUOJ2078-查找第k大(读入挂)
查找第k大 Submit Page Output 对于每组数据,输出第k大的数 Sample Input 1 6 2 1 2 3 4 5 6 Sample Output 5 Hint #include ...
- ESP8266调试(UDP调试)
1.设置STA模式 AT+CWMODE=1 2.加入热点 AT+CWJAP="Admin_name","password" 3.开启单路连接 AT+CIPMUX ...
- 笔记||Python3之字符串
字符串是Python中最常用的数据类型.我们可以使用引号('或''或''')来创建字符串. 三引号特点:可以多行,也可以多行注释. a = 'hello world' a = "hello ...
- Linq 常用操作(增删改)
增加 using(var db = new Entities()) { //数据操作 UserInfo user = new UserInfo() { UserName = "zhangsa ...
- 【系列专题】ECMAScript 重温系列(10篇全)
ES6 系列ECMAScript 2015 [ES]150-重温基础:ES6系列(一) [ES]151-重温基础:ES6系列(二) [ES]152-重温基础:ES6系列(三) [ES]153-重温基础 ...
- 为什么有ASP.NET
最近读了一些文章,总结一下: 在1999年,当时微软的windows系统运行的所有的应用程序都是有组件对象模型为根本基础开发的,用VB来处理数据访问和复杂的用户界面,缺点是不能使用函数指针,因为当时的 ...
- 【Zuul】使用学习
[Zuul]使用学习 添加依赖 <dependency> <groupId>org.springframework.cloud</groupId> <arti ...
- netty用法总结
/**decoder和encoder,如果不需要解析,就使用系统的 * ch.pipeline().addLast(new StringDecoder()); * ch.pipeline().addL ...
- 清晰架构(Clean Architecture)的Go微服务: 程序结构
我使用Go和gRPC创建了一个微服务,并试图找出最佳的程序结构,它可以用作我未来程序的模板. 我有Java背景,并发现自己在Java和Go之间挣扎,它们之间的编程理念完全不同.我写了一系列关于在项目工 ...