C99/C11数值计算增强
作者:追风剑情 发布于:2020-7-21 20:50 分类:C
过去,FORTRAN是数值科学计算和工程计算的首选语言。C90使C的计算方法更接近于FORTRAN。例如,float.h中使用的浮点特性规范都是基于FORTRAN标准委员会开发的模型。C99和C11标准继续增强了C的计算能力。例如C99新增的变长数组(C11成为可选的特性),比传统的C数组更符合FORTRAN的用法(如果实现不支持变长数组,C11指定了__STDC_NO_VLA__宏的值为1)。
IEC浮点标准
国际电工技术委员会(IEC)已经发布了一套浮点计算的标准(IEC 60559)。该标准包括了浮点数的格式、精度、NaN、无穷值、舍入规则、转换、异常以及推荐的函数和算法等。C99纳入了该标准,将其作为C实现浮点计算的指导标准。C99新增的大部分浮点工具(如,fenv.h头文件和一些新的数学函数)都基于此。另外,float.h头文件定义了一些与IEC浮点模型相关的宏。
1. 浮点模型
下面简要介绍一下浮点模型。标准把浮点数x看作是一个基数的某次幂乘以一个分数,而不是C语言的E记数法(例如,可以把876.54写成0.87954E3)。正式的浮点数表示更为复杂:
简单地说,这种表示法把一个数表示为有效数(significand)与b的e次幂的乘积。
下面是各部分的含义。
s代表符号(±1)。
b代表基数。最常见的值是2,因为浮点处理器通常使用二进制数学。
e代表整数指数(不要与自然对数中使用的数值常量e混淆),限制最小值和最大值。这些值依赖于留出储存指数的位数。
fk代表基数为b时可能的数字。例如,基数为2时,可能的数字是0和1;在十六进制中,可能的数字是0~F。
p代表精度,基数为b时,表示有效数的位数,其值受限于预留储存有效数字的位数。
明白这种表示法的关键是理解float.h和fenv.h的内容,下面,举两个例子解释内部如何表示浮点数。
首先,假设一个浮点数的基数b为10,精度p为5。那么,根据上面的表示法,24.51应写成:
(+1)103(2/10 + 4/100 + 5/1000 + 1/10000 + 0/100000)
假设计算机可储存十进制数(0~9),那么可以储存符号、指数3和5个fk值:2、4、5、1、0(这里f1是2,f2是4,等等)。因此,有效数是0.24510,乘以103得24.51。
接下来,假设符号为正,基数b是2,p是7(即,用7位二进制数表示),指数是5,待储存的有效数是1011001。下面,根据上面的公式构造该数:
x = (+1)25(1/2 + 0/4 + 1/8 + 1/16 + 0/32 + 0/64 + 1/128) = 32(1/2 + 0/4 + 1/8 + 1/16 + 0/32 + 0/64 + 1/128) = 16 + 0 + 4 + 2 + 0 + 0 + 1/4 = 22.25
float.h中的许多宏都与该浮点表示相关。例如,对于一个float类型的值,表示基数的FLT_RADIX是b,表示有效数位数(基数为b时)的FLT_MANT_DIG是p。
2. 正常值和低于正常的值
正常浮点值(normalized floating-point value)的概念非常重要,下面简要介绍一下。为简单起见,先假设系统使用十进制(b = FLT_RADIX = 10)和浮点值的精度为5(p = FLT_MANT_DIG = 5)(标准要求的精度更高)。考虑下面表示31.841的方式:
指数 = 3,有效数 = .31841(.31841E3)
指数 = 4,有效数 = .03184(.03184E4)
指数 = 5,有效数 = .00318(.00318E5)
显而易见,第1种方法精度最高,因为在有效数中使用了所有的5位可用位。规范化浮点非零值是第1位有效位为非零的值,这也是通常储存浮点数的方式。
现在,假设最小指数(FLT_MIN_EXP)是-10,那么最小的规范值是:
指数 = -10,有效数 = .10000(.10000E-10)
通常,乘以或除以10意味着使指数增大或减小,但是在这种情况下,如果除以10,却无法再减小指数。但是,可以改变有效数获得这种表示:
指数 = -10,有效数 = .01000(.01000E-10)
这个数被称为低于正常的(subnormal),因为该数并未使用有效数的全精度。例如,0.12343E-10除以10得.01234E-10,损失了一位的信息。
对于这个特例,0.1000E-10是最小的非零正常值(FLT_MIN),最小的非零低于正常值是0.00001E-10(FLT_TRUE_MIN)。
float.h中的宏FLT_HAS_SUBNURM、DBL_HAS_SUBNORM和LDBL_HAS_SUBNORM表征实现如何处理低于正常的值。下面是这些宏可能会用到的值及其含义:
-1 不确定(尚未统一)
0 不存在(例如,实现可能会用0替换低于正常的值)
1 存在
math.h库提供一些方法,包括fpclassify()和isnormal()宏,可以识别程序何时生成低于正常的值,这样会损失一些精度。
3. 求值方案
float.h中的宏FLT_EVAL_METHOD确定了实现采用何种浮点表达式的求值方案,如下所示(有些实现还会提供其他负值选项)。
-1 不确定
0 对在所有浮点类型范围和精度内的操作、常量求值
1 对在double类型的精度内和float、double类型的范围内的操作、常量求值,对long double范围内的long double类型的操作、常量求值
2 对所有浮点类型范围内和long double类型精度内的操作和常量求值
例如,假设程序中要把两个float类型的值相乘,并把乘积赋给第3个float类型变量。对于选项1(即K&R C采用的方案),这两个float类型的值将被扩展为double类型,使用double类型完成乘法计算,然后在赋值计算结果时再把乘积转为float类型。
如果选择0(ANSI C采用的方案),实现将直接使用这两个float类型的值相乘,然后赋值乘积。这样做比选项1快,但是会稍微损失一点精度。
4. 舍入
float.h中的宏FLT_ROUNDS确定了系统如何处理舍入,其指定值所对应的舍入方案如下所示。
-1 不确定
0 趋零截断
1 舍入到最接近的值
2 趋向正无穷
3 趋向负无穷
系统可以定义其他值,对应其他舍入方案。
一些系统提供控制舍入的方案,在这种情况下,fenv.h中的festround()函数提供编程控制。
如果只是计算制作37个蛋糕需要多少面粉,这些不同的舍入方案可能并不重要,但是对于金融和科学计算而言,这很重要。显然,把较高精度的浮点值转换成较低精度值时需要使用舍入方案。例如,把double类型的计算结果赋给float类型的变量。另外,在改变进制时,也会用到舍入方案。不同进制下精确表示的分数不同。例如,考虑下面的代码:
float x = 0.8;
在十进制下,8/10或4/5都可以精确表示0.8。但是大部分计算机系统都以二进制储存结果,在二进制下,4/5表示为一个无限循环小数:
0.1100110011001100...
因此,在把0.8储存在x中时,将其舍入为一个近似值,其具体取决于使用的舍入方案。
尽管如此,有些实现可能不满足IEC 60559的要求。例如,底层硬件可能无法满足要求。因此,C99定义了两个可用作预处理器指令的宏,检查实现是否符合规范。第1个宏是__STDC_IEC_559,如果实现遵循IEC 60559浮点规范,该宏被定义为常量1。第2个宏是__STDC_IEC_559_COMPLEX__,如果实现遵循IEC 60559兼容复数运算,该宏被定义为常量1。如果实现中未定义这两个宏,则不能保证遵循IEC 60559。
标签: C语言
日历
最新文章
随机文章
热门文章
分类
存档
- 2024年11月(3)
- 2024年10月(5)
- 2024年9月(3)
- 2024年8月(3)
- 2024年7月(11)
- 2024年6月(3)
- 2024年5月(9)
- 2024年4月(10)
- 2024年3月(11)
- 2024年2月(24)
- 2024年1月(12)
- 2023年12月(3)
- 2023年11月(9)
- 2023年10月(7)
- 2023年9月(2)
- 2023年8月(7)
- 2023年7月(9)
- 2023年6月(6)
- 2023年5月(7)
- 2023年4月(11)
- 2023年3月(6)
- 2023年2月(11)
- 2023年1月(8)
- 2022年12月(2)
- 2022年11月(4)
- 2022年10月(10)
- 2022年9月(2)
- 2022年8月(13)
- 2022年7月(7)
- 2022年6月(11)
- 2022年5月(18)
- 2022年4月(29)
- 2022年3月(5)
- 2022年2月(6)
- 2022年1月(8)
- 2021年12月(5)
- 2021年11月(3)
- 2021年10月(4)
- 2021年9月(9)
- 2021年8月(14)
- 2021年7月(8)
- 2021年6月(5)
- 2021年5月(2)
- 2021年4月(3)
- 2021年3月(7)
- 2021年2月(2)
- 2021年1月(8)
- 2020年12月(7)
- 2020年11月(2)
- 2020年10月(6)
- 2020年9月(9)
- 2020年8月(10)
- 2020年7月(9)
- 2020年6月(18)
- 2020年5月(4)
- 2020年4月(25)
- 2020年3月(38)
- 2020年1月(21)
- 2019年12月(13)
- 2019年11月(29)
- 2019年10月(44)
- 2019年9月(17)
- 2019年8月(18)
- 2019年7月(25)
- 2019年6月(25)
- 2019年5月(17)
- 2019年4月(10)
- 2019年3月(36)
- 2019年2月(35)
- 2019年1月(28)
- 2018年12月(30)
- 2018年11月(22)
- 2018年10月(4)
- 2018年9月(7)
- 2018年8月(13)
- 2018年7月(13)
- 2018年6月(6)
- 2018年5月(5)
- 2018年4月(13)
- 2018年3月(5)
- 2018年2月(3)
- 2018年1月(8)
- 2017年12月(35)
- 2017年11月(17)
- 2017年10月(16)
- 2017年9月(17)
- 2017年8月(20)
- 2017年7月(34)
- 2017年6月(17)
- 2017年5月(15)
- 2017年4月(32)
- 2017年3月(8)
- 2017年2月(2)
- 2017年1月(5)
- 2016年12月(14)
- 2016年11月(26)
- 2016年10月(12)
- 2016年9月(25)
- 2016年8月(32)
- 2016年7月(14)
- 2016年6月(21)
- 2016年5月(17)
- 2016年4月(13)
- 2016年3月(8)
- 2016年2月(8)
- 2016年1月(18)
- 2015年12月(13)
- 2015年11月(15)
- 2015年10月(12)
- 2015年9月(18)
- 2015年8月(21)
- 2015年7月(35)
- 2015年6月(13)
- 2015年5月(9)
- 2015年4月(4)
- 2015年3月(5)
- 2015年2月(4)
- 2015年1月(13)
- 2014年12月(7)
- 2014年11月(5)
- 2014年10月(4)
- 2014年9月(8)
- 2014年8月(16)
- 2014年7月(26)
- 2014年6月(22)
- 2014年5月(28)
- 2014年4月(15)
友情链接
- Unity官网
- Unity圣典
- Unity在线手册
- Unity中文手册(圣典)
- Unity官方中文论坛
- Unity游戏蛮牛用户文档
- Unity下载存档
- Unity引擎源码下载
- Unity服务
- Unity Ads
- wiki.unity3d
- Visual Studio Code官网
- SenseAR开发文档
- MSDN
- C# 参考
- C# 编程指南
- .NET Framework类库
- .NET 文档
- .NET 开发
- WPF官方文档
- uLua
- xLua
- SharpZipLib
- Protobuf-net
- Protobuf.js
- OpenSSL
- OPEN CASCADE
- JSON
- MessagePack
- C在线工具
- 游戏蛮牛
- GreenVPN
- 聚合数据
- 热云
- 融云
- 腾讯云
- 腾讯开放平台
- 腾讯游戏服务
- 腾讯游戏开发者平台
- 腾讯课堂
- 微信开放平台
- 腾讯实时音视频
- 腾讯即时通信IM
- 微信公众平台技术文档
- 白鹭引擎官网
- 白鹭引擎开放平台
- 白鹭引擎开发文档
- FairyGUI编辑器
- PureMVC-TypeScript
- 讯飞开放平台
- 亲加通讯云
- Cygwin
- Mono开发者联盟
- Scut游戏服务器引擎
- KBEngine游戏服务器引擎
- Photon游戏服务器引擎
- 码云
- SharpSvn
- 腾讯bugly
- 4399原创平台
- 开源中国
- Firebase
- Firebase-Admob-Unity
- google-services-unity
- Firebase SDK for Unity
- Google-Firebase-SDK
- AppsFlyer SDK
- android-repository
- CQASO
- Facebook开发者平台
- gradle下载
- GradleBuildTool下载
- Android Developers
- Google中国开发者
- AndroidDevTools
- Android社区
- Android开发工具
- Google Play Games Services
- Google商店
- Google APIs for Android
- 金钱豹VPN
- TouchSense SDK
- MakeHuman
- Online RSA Key Converter
- Windows UWP应用
- Visual Studio For Unity
- Open CASCADE Technology
- 慕课网
- 阿里云服务器ECS
- 在线免费文字转语音系统
- AI Studio
- 网云穿
- 百度网盘开放平台
- 迅捷画图
- 菜鸟工具
- [CSDN] 程序员研修院
- 华为人脸识别
- 百度AR导航导览SDK
- 海康威视官网
- 海康开放平台
- 海康SDK下载
- git download
交流QQ群
-
Flash游戏设计: 86184192
Unity游戏设计: 171855449
游戏设计订阅号