浮点数精度问题(比特与信息在计算机中的表示及补码和浮点数的IEEE)
比特(bit,binary digit的缩写)中文翻译为“二进位数字”、“二进位” 或简称为 “位”,我来为大家科普一下关于浮点数精度问题?以下内容希望对你有帮助!
浮点数精度问题
1 什么是比特?比特(bit,binary digit的缩写)中文翻译为“二进位数字”、“二进位” 或简称为 “位”。
比特只有 2 种取值:0和1,一般无大小之分。
如同DNA是人体组织的最小单位、原子是物质的最小组成单位一样,比特是组成数字信息的最小单位。
数值、文字、符号、图像、声音、命令······都可以使用比特来表示。
2 比特的三种基本逻辑运算比特的取值“0”和“1” 可表示两种不同的状态(例如电位的高/低、开关的断开/接通)。
比特的运算使用逻辑代数,它有3种基本逻辑运算:
逻辑加(也称“或”运算,用符号“OR”、“∨”或“+”表示)。
逻辑乘(也称“与”运算,用符号“AND”、 “∧”或“ · ”表示,也可省略)。
取反(也称“非”运算,用符号“NOT”或上横杠“¯”表示)。
两个多位的二进制信息进行逻辑运算时,按位独立进行,即每一位都不受其它位的影响:
例1
A:0110 ∨ B:1010 F: 1110
例2
A: 0110∧ B: 1010 F: 0010
3 比特在计算机中如何表示?表示一个比特需要使用两个状态:
电路的高电平状态或低电平状态(CPU)
电容的充电状态或放电状态(RAM)
两种不同的磁化状态(磁盘)
光盘面上的凹凸状态(光盘)
···
4 比特的存储存储(记忆)1个比特需要使用具有两种稳定状态的元器件,例如:开关、灯泡等。
4.1 比特在CPU中的存储
在计算机的CPU中,比特使用一种称为“触发器”的双稳态电路来存储。
触发器有两个状态,可分别用来记忆0和1,1个触发器可存储1个比特。
一组(例如8个或16个)触发器可以存储1组比特,称为“寄存器”。
CPU中有几十个甚至上百个寄存器。
断电后信息不再保持、为易失性存储器!
4.2 比特在内存中的存储
计算机存储器中用电容器存储二进位信息:当电容的两极被加上电压,它就被充电,电压去掉后,充电状态仍可保持一段时间,因而1个电容可用来存储1个比特。
电容C处于充电状态时,表示1
电容C处于放电状态时,表示0
集成电路技术可以在半导体芯片上制作出以亿计的微型电容器,从而构成了可存储大量二进位信息的半导体存储器芯片。
断电后信息不再保持!
4.3 比特在外存储器中的存储
磁盘:利用磁介质表面区域的磁化状态来存储二进位信息。
光盘:只读光盘通过“刻”在光盘片表面上的微小凹坑来记录二进位信息。
断电后信息可以保持、为非易失性存储器!
5 存储容量的计量单位8个比特=1个字节(byte,用大写B表示)
计算机内存储器容量的计量单位:
KB: 1 KB=2^10字节=1024 B (千字节) MB: 1 MB=2^20字节=1024 KB(兆字节) GB: 1 GB=2^30字节=1024 MB(吉字节、千兆字节) TB: 1 TB=2^40字节=1024 GB(太字节、兆兆字节)
外存储器容量经常使用10的幂次来计算:
1MB=10^3 KB =1 000 KB 1GB=10^6 KB =1 000 000 KB 1TB= 10^9 KB = 1 000 000 000 KB
不同进位制前缀的使用场合:
内存、cache、半导体存储器芯片的容量均使用二进制前缀:
512MB的内存条( 1M=2^20 )
256KB 的cache(1K= 2^10 )
文件和文件夹的大小使用二进制前缀。
频率、传输速率等使用十进制前缀:
主频 1GHz(1G=10^9)
传输速率 100Mbps(1M=10有^6)
外存储器(硬盘、DVD光盘、U盘、存储卡等)容量:
厂商标注的容量使用十进制前缀。
操作系统显示的容量使用二进制前缀。
6 比特的传输信息是可以传输的,信息只有通过传输和交流才能发挥它的作用。
在数字通信技术中,信息的传输是通过比特的传输来实现的。
近距离传输时:直接将用于表示“0/1”的电信号或光信号进行传输(称为基带传输),例如:
计算机读出或者写入移动硬盘中的文件。
使用打印机打印某个文档的内容。
远距离传输或者无线传输时:需要使用调制技术。
比特的传输速率:
传输速率表示每秒钟可传输的二进位数目,常用单位是:
比特/秒(b/s),也称“bps”。如 2400 bps(2400b/s) 千比特/秒(kb/s),1kb/s=103比特/秒=1 000 b/s 兆比特/秒(Mb/s),1Mb/s=106比特/秒=1 000 kb/s 吉比特/秒(Gb/s),1Gb/s=109比特/秒=1 000 Mb/s 太比特/秒(Tb/s),1Tb/s=1012比特/秒=1 000 Gb/s
8 不同进位制数的表示和含义“数”是一种信息,它有大小(数值),可以进行四则运算。
“数”有不同的表示方法。日常生活中人们使用的是十进制数,但计算机使用的是二进制数,程序员还使用八进制和十六进制数,它们怎样表示?其数值如何计算?
8.1 十进制数
每一位可使用十个不同数字表示(0、1、2、3、4、5、6、7、8、9)。
低位与高位的关系是:逢10进1。
各位的权值是10的整数次幂(基数是10 )。
标志: 尾部加“D”或缺省。
例:
204.96=2×10^2+0×10^1+4×10^0+9×10^-1+6×10^-2
8.2 二进制数
每一位使用两个不同数字表示(0、1),即每一位使用 1 个“比特”表示。
低位与高位的关系是:逢2进1。
各位的权值是 2 的整数次幂(基数是2 )。
标志: 尾部加B
例:
101.01 B =1×2^2+0×2^1+1×2^0 +0×2^-1+1×2^-2 =5.25
8.3 十六进制数
用十六进制数来表示二进制数,相当于二进制数来说,更直观,因为4个二进制位可以用1个十六进制位来表示,因为二进制的1111等于十进制的15,也就是十六进制的F。十进制与二进制的位数对位没有十六进制方便,一位十进制相当于约3.2位二进制。
每一位使用十六个数字和符号表示(0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F )。
逢16进1, 基数为16。
各位的权值是16的整数次幂(基数是16 )。
标志:尾部加H。
例:
F5.4H=15×16^1 5×16^0 4×16^-1 = 245.25
8.4 八进制数
一位八进制数可以表示三位二进制数,因为二进制的111也就是八进制的7。
每一位使用八个不同数字表示(0、1、2、3、4、5、6、7)。
低位与高位的关系是:逢8进1。
各位的权值是8的整数次幂(基数是8 )。
标志:尾部加Q。
例:
365.2Q = 3×8^2 6×8^1 5×8^0 2×8^-1 = 245.25
9 不同进制数的相互转换熟练掌握不同进制数相互之间的转换,在编写程序和设计数字逻辑电路时很有用。
只要学会二进制数与十进制数之间的转换,与八进制、十六进制数的转换就不在话下了。
9.1 十进制数→二进制数
转换方法:
整数和小数分开转换。
整数部分:除以2逆序取余
小数部分:乘以2顺序取整
例如:29.6875→ 11101.1011 B
注意:十进制小数(如0.63)在转换时会出现二进制无穷小数,这时只能取近似值。
9.2 二进制数→十进制数
转换方法:
二进制数的每一位乘以其相应的权值,然后累加即可得到它的十进制数值。
例: 11101.1011B
= 1×2^4+1×2^3+1×2^2+0×2^1+1×2^0
+1×2^-1+0×2^-2+1×2^-3+1×2^-4
= 29.6875
9.3 八进制数与二进制数的互换
八进制→二进制:把每个八进制数字改写成等值的3位二进制数,且保持高低位的次序不变。
例: 2467.32Q → 010 100 110 111 . 011 010 B
二进制→八进制:整数部分从低位向高位每3位用一个等值的八进制数来替换,不足3位时在高位补0凑满3位;小数部分从高位向低位每3位用一个等值八进制数来替换,不足3位时在低位补0凑满三位。
例: 1 101 001 110.110 01 B → 001 101 001 110.110 010 B
→ 1516.62 Q
9.4 十六进制数与二进制数的互换
转换方法:与八、二进制互换的方法类似。
例1:35A2.CFH → 11 0101 1010 0010.1100 1111B
例2:11 0100 1110.1100 11B → 34E.CCH
10 PC机中数的主要类型都采用二进制表示,有不同类型和不同长度。
不同类型和不同长度的数各有不同的用途。
10.1 无符号整数的表示
10.2 有符号整数的表示
负数的绝对值如何用补码表示?
先表示为自然码。
将自然码的每一位取反码。
在最低位加“1”。
如4个位的补码方案可以表示的数据范围:
10.3 原码和补码的优缺点分析
原码表示法:
优点:与日常使用的十进制表示方法一致,简单直观。
缺点:加法与减法运算规则不统一,增加了成本;整数0 有“00000000”和“10000000”两种表示形式,不方便。
补码表示法:
优点:加法与减法运算规则统一, 没有“-0”,可表示的数比原码多一个(-2n-1)。
缺点:不直观,人使用不方便。
10.4 原码和补码可表示的整数范围
原码可表示的整数范围:
8位原码: - 27 1~27- 1(- 127~127)
16位原码: - 215 1~215- 1(- 32767~32767)
n 位原码: - 2n-1 1~2n-1- 1
补码可表示的整数范围:
8位补码:- 27~27- 1 (- 128~127 )
n位补码:- 2n-1~2n-1- 1
- 128表示为 10000000
127 表示为 01111111
10.5 整数在计算机中的表示的对比
计算机中整数有多种,同一个二进制代码表示不同类型的整数时,其含义(数值)可能不同。
一个代码它到底代表哪种整数(或其它东西),是由指令决定的。
10.6 实数的特点与表示方法
实数是既有整数部分又有小数部分,小数点位置不固定。
任何一个实数总可以表达成一个乘幂和一个纯小数之积。
例如:
56.725 = 0.56725×10^2
-0.0034756 = -0.34756×10^-2
实数的表示方法(记阶法/浮点表示法):用3个部分表示:
乘幂中的指数(也称阶码):表示实数中小数点的位置。
纯小数部分(尾数):表示实数中的有效数字部分。
数的正负(符号)。
二进制实数的浮点表示:
与十进制实数一样,二进制实数也可以用记阶法表示,如:
1001.011B = 0.1001011B×2^ 100
-0.0010101B = -0.10101B×2^-10
可见,任一个二进制实数 N 均可表示为:
N=±S×2P
(其中, ±是该数的符号; S是N 的尾数;P是N的阶码)
因此,32位的单精度浮点数在计算机中可表示为:
由于指数(阶码)可以选用不同的编码(原码、补码等),尾数的格式和小数点位置也可以有不同的规定,因此早期计算机中浮点数的表示方法互不相同。
现代计算机中,一般都以IEEE 754标准存储浮点数,这个标准的在内存中存储的形式为:
对于不同长度的浮点数,阶码与小数位分配的数量不一样,如对于32位的单精度浮点数,数符分配是1位,阶码分配了8位,尾数分配了是23位:
符号位:0表示正;1表示负;
偏移阶码e:e=指数的实际值 127。
假有一个浮点数10110010.001,则指数是7,阶码就要用7 127的二进制数表示,也就是:111 01111111 = 10000110
尾数使用原码表示,绝对值在1与2之间,其中1和小数点都是隐含的,并不直接表示。
根据这个标准,我们来尝试把一个十进制的浮点数转换为IEEE754标准表示。
例如:178.125
先把浮点数分别把整数部分和小数部分转换成2进制:
整数部分用除2取余的方法,求得:10110010
小数部分用乘2取整的方法,求得:001
合起来即是:10110010.001
转换成二进制的浮点数,即把小数点移动到整数位只有1,即为:1.0110010001 * 2^111,111是二进制,由于左移了7位,所以是111
把浮点数转换二进制后,这里基本已经可以得出对应3部分的值了:
数符:由于浮点数是正数,故为0(负数为1)。
阶码 : 阶码的计算公式:阶数 偏移量, 阶码是需要作移码运算,在转换出来的二进制数里,阶数是111(十进制为7),对于单精度的浮点数,偏移值为01111111(127)[偏移量的计算是:2^(e-1)-1, e为阶码的位数,即为8,因此偏移值是127],即:111 01111111 = 10000110
尾数:小数点后面的数,即0110010001
最终根据位置填到对位的位置上:
可能有个疑问:小数点前面的1去哪里了?由于尾数部分是规格化表示的,最高位总是“1”,所以这是直接隐藏掉,同时也节省了1个位出来存储小数,提高精度。
浮点数的二进制显示可以使用以下代码:
#include<iostream> #include <bitset> //STL的bitset模板类 using namespace std; void main() { union { float input; int output; } data; data.input = 178.125; std::bitset<sizeof(float) * 8>bits2(data.output); //bitset模板类定义对象,<>内为长度,()为值 //如bitset<8> bitset2(12); //长度为8,二进制保存,前面用0补充 std::cout << bits2 << std::endl; system("pause"); } //01000011001100100010000000000000
-End-
免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com