浮点运算与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 - ...
随机推荐
- HDU1529-Casher Emploryment(最最...最经典的差分约束 差分约束-最长路+将环变线)
A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit its n ...
- 2018HDU多校训练一 K - Time Zone
Chiaki often participates in international competitive programming contests. The time zone becomes a ...
- eviews面板数据的操作
数据结构: 打开eviews File>new>workfile Object>new object > pool 输入城市名称: _bj 下划线加名称(必须是英文),竖着输入 ...
- Java 从入门到进阶之路(十三)
在之前的文章我们介绍了一下 Java 类的 private,static,final,本章我们来看一下 Java 中的抽象类和抽象方法. 我们先来看下面一段代码: // 根据周长求面积 class S ...
- 咪咕音乐链接歌词封面搜索等接口API
搜索 pd.musicapp.migu.cn/MIGUM2.0/v1.0/content/search_all.do?&ua=Android_migu&version=5.0.1&am ...
- vue hover如何触发事件?
vue中并没有 @hover 事件,但是可以使用 @mouseenter 和 @mouseleave 来模拟hover操作.
- Python面向对象-访问权限public和private
上一节我们介绍了,Class内部可以有属性和方法,外部代码通过直接调用实例的方法来操作数据,这样就可以隐藏内部的逻辑实现:同时,外部代码还是可以自由的修改实例的属性和增加方法. 但是有时候,我们不想这 ...
- C#中提示:当前上下文中不存在名称“ConfigurationManager”
场景 想要在程序中获取App.config中设置的内容. 想要通过 ConfigurationManager.AppSettings[key]; 来进行获取,已经添加 using System.Con ...
- linux环境下zookeeper下载安装
步骤一:安装配置jdk环境 1.下载解压jdk-8u221-linux-x64.tar.gz 2.打开 配置文件,vim /etc/profile,添加如下配置,添加完成记得source /etc/p ...
- mysql-magic 从dump中获取MySQL的明文密码
项目地址: https://github.com/hc0d3r/mysql-magic 安装: git clone --recurse-submodules https://github.com/hc ...