浮点数的存储结构和开发时候的注意事项
来源:互联网 发布:电力调度中心知乎 编辑:程序博客网 时间:2024/04/29 06:52
Overview
在我们现在的计算系统中, 浮点数是以 IEEE 754 为标准的. 他的表示方式类似数学里提到的科学记数法.这种表示方式是用符号位 ( Sign )、指数 ( Exponent ) 、尾数 ( Mantissa )或者 也可以叫 Significand ( 有效位数 ) , 三者的组合来表达一个数字的.
所以最好再开始看计算机中浮点数的表示方式前.首先简单回顾一下,小时候数学课中对科学记数法的描述.随后再了解编程中的浮点数.最后再看一下常有的注意事项.
所以最好再开始看计算机中浮点数的表示方式前.首先简单回顾一下,小时候数学课中对科学记数法的描述.随后再了解编程中的浮点数.最后再看一下常有的注意事项.
科学记数法 ( Scientific notation )
(大部分定义、推论.都出自 http://en.wikipedia.org )
定义:
一个数被写成一个1与10之间的实数(尾数)与一个10的幂的积,为了得到统一的表达方式,该尾数並不包括10.
比如:
782300 = 7.823 × 105
0.00012 = 1.2 × 10−4
10000 = 1×104
0.00012 = 1.2 × 10−4
10000 = 1×104
推论 (科学记数的基本计算 乘、除法) :
假设有两个以科学计数法表示的数字:
则有:
则有:
推论 (科学记数的基本计算 加、减法) :
同样先假设有两个以科学计数法表示的数字:
再做加、减法前先要把 X1 重新计算一下. 求出一个新的 c, 必须满足以下条件.
接着就可以得到:
举实际例子来说:
再做加、减法前先要把 X1 重新计算一下. 求出一个新的 c, 必须满足以下条件.
接着就可以得到:
举实际例子来说:
C/C++ 程序中的浮点数
计算机程序中的浮点数的表示方式也类似上面提到的方式.只是在计算机中是以 2 为底数,而不是 10.
需要注意:
需要注意:
- Intel CPU 是采用 little-endian ( The most significant byte is on the right end of a word. ) 所以在观察内存时是需要反过来读的.
- 有一些编译器 和 平台支持精度更高的 Double-Extended
- C/C++ 编译器中的浮点数表示方式如下表所示.
符号位 ( Sign ) 指数 ( Exponent ) 尾数 ( Mantissa ) 单精度浮点数 ( float ) 1 [31] 8 [30-23] 23 [22-00] 双精度浮点数 ( double ) 1 [63] 11 [62-52] 52 [51-00]
- 符号
符号位占用一位.在最高位. 0 表示正数. 1 表示负数.
- 指数
以 float 为例 指数位 占用 8 为, 他的表示范围是. -127 ~ +128. 但是 -127 和 +128 这 2 个数字是保留用作表示特殊状态的. ( -127 用来表示 这个是 0, 即 Zero 状态. +128 一般用来表示NaN 状态. NaN 是指 Not a Number. 不是一个实际的数字. )
这 8 位在做计算是要注意范围是从 -127 ~ +128 的,所以在计算是要减去 127.
比如有这 8位的指数2进制如下:
10000000
所以这个指数表示的是: 10000000b = 128 考虑到范围所以 128 - 127 = 1
当精度为 double 时也是这样的,只是表示范围是 -1023 ~ +1024 .
- 尾数
尾数又叫有效位数 ( Significand ), 他和 科学记数中的尾数一样是用来表示这个数字的大小 和 精确度的.
尾数的格式是 1.F. 其中 F 是对应的 小数位. 整数部分的 1 是在计算中省略的.
尾数的格式是 1.F. 其中 F 是对应的 小数位. 整数部分的 1 是在计算中省略的.
- 举实际例子来说
比如:
有十进制 +5.5, 则有
+5.5 = 1.375 × 22
随后把 尾数换算成 2 进制.
1.375 = 1 .011 B ( 即, 1 × 21 + 1 × 2-2 + 1 × 2-3)
由于 float 中尾数占用 23 位,所以要不齐那些无用的 0, 就得出 尾数为.
1 .01100000000000000000000
指数位是 2,由于 float 变换范围是 -127 ~ +128 占用 8 位. 所以指数位应该等于 2 + 127 = 10000001b
所以就有 2 进制表示.
符号位 ( Sign ) 指数 ( Exponent ) 尾数 ( Mantissa ) 01000000101100000000000000000000
得出 +5.5 = 01000000101100000000000000000000B = 0x40B00000
因为 little-endian 的关系,所以在内存中观察是反序的,即 [ 00 00 B0 40 ]
因为 little-endian 的关系,所以在内存中观察是反序的,即 [ 00 00 B0 40 ]
开发时的注意事项
- 比较操作
- 比较操作
不可将浮点变量用 “==” 或 “!=” 与任何数字比较.千万要留意,无论是float 还是double 类型的变量,都有精度限制.
所以一定要避免将浮点变量用 “==” 或 “!=” 与数字比较,应该设法转化成 “>=” 或 “<=” 形式.
所以一定要避免将浮点变量用 “==” 或 “!=” 与数字比较,应该设法转化成 “>=” 或 “<=” 形式.
假设浮点变量的名字为x,应当将
if (x == 0.0) // 隐含错误的比较
转化为
if ((x>=-PRECISION) && (x<=PRECISION))
其中PRECISION 是允许的误差(即精度).如果不是和 0 比较,则可用 与比较值之间的差值的绝对值与精度比较.比如: x 与 y 的比较可写成 fabs( x - y ) < PRECISION
- 位运算
正常情况下不要用 浮点数去做位运算.即使是你清楚浮点的存储结构.
理由有二. 1. 不便于他人维护代码. 2. 可能有编译器不兼容问题.
理由有二. 1. 不便于他人维护代码. 2. 可能有编译器不兼容问题.
Appendix
- 浮点数运算的介绍http://steve.hollasch.net/cgindex/coding/ieeefloat.html
- 浮点数转换运算的网页工具http://babbage.cs.qc.edu/IEEE-754/
- 在 Attachments 里有 IEEE 754 的说明文件. (IEEE 754 是计算机中的浮点数标准) PS格式,可以用 GSView 浏览这个文件. (ieee754.ps )
转载:http://sites.google.com/site/whirlpoolsite/float
- 浮点数的存储结构和开发时候的注意事项
- C++ 浮点数的存储结构
- 浮点数的存储
- 浮点数的存储
- 浮点数的存储
- 浮点数的存储
- 浮点数的存储
- 浮点数的存储
- 浮点数的存储
- 浮点数的存储
- 四极管:浮点数的存储和转换
- C语言中的float浮点数的存储结构。
- 浮点数的内存结构
- 浮点数的内存结构
- 浮点数的内存结构
- 浮点数的存储形式
- 浮点数的存储方式
- 浮点数的存储方式
- undefined reference to gettid
- dwr2.0 中 util.js脚本提供的实用方法调用说明
- 实践经验(乱码?注意顺序!)
- android study ------ HAL ---> light sensor
- Struts2自定义拦截器实例—登陆权限验证 .
- 浮点数的存储结构和开发时候的注意事项
- AjaxControlToolkit的安装与使用
- LR中的参数
- 视图动画效果 通过layer层实现
- 对Amazon EBS 的测试
- 中国和周边国家勘界后:真实国土面积大曝光
- silverlight datagrid动态生成列&动态绑定
- Ext.data.GroupingStore 从后台获取数据
- riak源码阅读手记一 初出茅庐 项目入口