c 浮点数
一、二进制小数
十进制小数: 12.3410 == 1 * 101 + 2 * 100 + 3 * 10-1 + 4 * 10-2 = 12(34/100)
(可能很多人还不知道怎么计算一个数的负幂,这里给大家一个方法:一个数的负的X次方等于这个数的X次方分之一,比如2-2 = 0.25 = 1/2*2 = 1/4,现在明白不?)
二进制小数:101.11 == 1 * 22 + 0 * 21 + 1 * 20 + 1 * 2-1 + 1 * 2-2 = 4 + 0 + 1 + 1/2 + 1/4 = 5(3/4)
从二进制小数可以看出点左边的位的权是2的正幂;而点右边的位是2的负幂
下图是数b的定义:
从该图中不难看出有两种情况:
a>. 把小数点向左移动一位的时候相当于这个数被除以2(比如:101.112 = 5.75 --- 往左移动一位 -->10.1112 = 1 * 22 + 0 * 21 + 1 * 2-1 + 1 * 2-2 +1 * 2-3 = 2 + 0 + 1/2 + 1/4 + 1/8 = 2(7/8) = 2.875,)
b>. 把小数点向右移动一位的时候相当于这个数被乘于2(比如:101.112 = 5.75 --- 往左移动一位 -->1011.12 = 1 * 23 + 0 * 22 + 1 * 21 + 1 * 20 +1 * 2-1 = 8 + 0 + 2 + 1 + 1/2 = 11(1/2) = 11.5)
注意:
a>. 比如0.1,11112这样的数,刚好小于1,这样的数表示(63/64),我们使用科学计数法来表示:1.0-€
b>. 比如1/3、5/7这样的数,就是二进制小数所表单不了的,二进制小数表示法只能表示那些能够被写成x * 2y 的数
下面是一些题目,咱们借着题目分析一下(这个题目是深入理解计算机系统第三版的练习题):
疑问:
1.如何知道二进制小数部分有几位小数? 答:看分母,将分母换算成二进制,得到n位二进制数再减1(8 = 1000 = 4-1 = 3),比如1/8 = 0.001、1/2 = 0.1、1/16 = 0.0001
2.分子换算成小数部分后从小数点往右 位权越大还是越小? 答:从小数点往右二进制位的权越来越小,比如:1/16 =0.0001(有人计算出来是0.1000,这样是错的,这样的结果就是8/16 = 1/2 = 0.5 = 5 * 10-1 = 5/10 = )-------->这里涉及到十进制小数转二进制小数的问题,就是用小数去乘以2,不断的取整数:0.5 * 2 = 1.0 取1,小数部分就是1,结果就是0.1,一直乘以2,知道结果为1.0位置
a>. 3/8,首先分子比分母小,结果小于1;分母为8抓成二进制1000,小数部分则是n-1 = 3,分子部分011(是从右往左的),结果就是0.011;十进制:0.(1 * 2^-2 + 1 * 2^-3) = 3/8 = 0.375
b>. 23/16,首先分子大于分母,结果大于1,先计算整数部分为1,剩余为7/16,确定几位小数16 = 10000,小数位n-1 = 4,分子转成4位二进制 = 0111,结果就是1.0111;十进制:1 * 2^0 + 1 * 2^-2 + 1 * 2^-3 + 1 * 2^-4 = 1 + 0.25 + 0.125 + 0.0625 = 1.4375
c>. 10.1101,逆向运算 1 * 2^1 + 1 * 2^-1 + 1 * 2^-2 + 1 * 2^-4 = 2 + 1/2 + 1/4 + 1/16 = 2 + 13/16 = 45/16;十进制:2.8125
d>. 1.011 === 1 * 2^1 + 1 * 2^-2 + 1 * 2^-3 = 1 + 4/8 + 1/8 = 13/8 = 1.625
e>. 5.375 首先整数部分是5 = 101,小数部分是0.375,按照十进制小数转二进制小数,不断乘2,取整数(011),小数部分是011,结果就是101.011;小数值:5(3/8) = 43/8
f>.3.0625 首先整数部分是3 = 11,小数部分0.0625 = 0001,结果就是11.0001;小数值:3(1/16) = 49/16
二、IEEE浮点表示
IEEE浮点标准(表示一个数):V = (-1)s * M * 2E (不太理解)
介绍:
符号(s):决定数是负数(s == 1)还是整数(s == 0),而对于数值0的符号位解释作为特殊情况处理
有效数(M):它是一个二进制小数,它的范围在1~2-€或者0~1-€之间
指数(E):2的幂(正负都有可能),它的作用是对浮点数加权
浮点数的位分为三个域,编码值:
符号位(s):决定正负
尾数(M):一个二进制小数
阶码(E):对浮点数加权
存储一个浮点数(s正负号、exp指数E,frac小数部分):
对于单精度浮点格式(32位):
对于双精度浮点格式(64位):
根据阶码(E)字段的值不同我们可以分为四类浮点数:
a>. 规格化浮点数:
规格化浮点数:阶码值E = e - bias(2k-1 -1),bias在单精度情况下是127,双精度情况下是1023,因此单精度下E的值为[-126~+127],在双精度下E的值为[-1022~+1023];对于小数字段frac,f =0. fn-1fn-2.....f0,而位数M = f +1;在这里我们将浮点数的首位默认为1,所以没有显示的存储在存储器中,为什么能这样呢?因为我们可以通过调整阶码值E,使小数部分二进制的值落在1~2之间,获得额外的精度为
例如:0.10111,存储的话小数部分的二进制位是5位,存储就是000...10111,但是浮点数首位默认为1之后,我们小数部分存4位就可以了,1.0111 * 2-1 (why??前面咱们提到过,二进制小数,小数点往左移动一位就是除以2,往右移动就是乘以2,在这里我们往右移动了一位,结果就是1.0111,那么我们还原回去保持值不变就必须除以2,也就是*1/2)
表示范围:单精度下[-2^127,2^127],双精度下[-2^1023,2^1023],那么规范化的绝对值是大于 2 ^ (-126) 或 2 ^ (-1022) 的数字
示例1:0.25,先转成二进制小数0.01,那么根据规范化的属性转换一种形式,小数点往右移动2位 (0.01 * 2^2) * 2^-2 = 1.0 * 2^-2,根据阶码值计算E = -2 + 127 = 125,二进制小数部分全部都是0,那么最后的结果就是0 0111 1101 0000 0000 0000 0000 0000 000
示例2:1.5,转成二进制1.1,规格化默认首位为1,先忽略,0.1 * 2^0,那么阶码E = 127 + 0 = 127 = 01111111,小数部分1,后边补齐0即可,结果就是0 0111 1111 1000 0000 0000 0000 0000 000
b>. 非规格化浮点数:
非规格化浮点数:定义阶码E = 1 - bias (2k-1 -1),M = f = 0.fn-1 fn-2 fn-3 …… f2 f1 f0
表示范围:非规范化浮点数表示的则是小于 2 ^ (-126) 或 2 ^ (-1022) 的值
c>. 无穷大:
无穷大:frac部分二进制小数全为0
d>. NaN(Not a Number)
NaN:frac部分二进制小数不全为0
下边是几个文章的链接(写的特别好):
http://blog.csdn.net/hqin6/article/details/6701109
http://www.atjiang.com/CSAPP3-2.4_floating_point/
https://yasicyu.com/newarticle/IEEE-754%E6%A0%87%E5%87%86%E4%B8%8E%E5%AE%9E%E7%8E%B0
下面是一些练习题,本人对这一部分不是很懂,所以记录一下面试题的分析过程:
IEEE浮点格式的5位浮点数表示,1位符号位、2个指数位(k=2)和2位小数,指数偏移量bias = 2k-1 - 1 = 1
注意(0 00 00):
1.IEEE754浮点数表达式: V = M * 2e bias = 2k-1 - 1 = 1
2. 规格化数:E = e - Bias = e - 2k-1 - 1;M = f + 1
2.1 规格化数的范围:小数部分 0+1 = 1 ~ 1+3/4 = 7/4, V的范围 1 * 2^-1 = 1/2 ~ 2 * 7/4 = 14/4
3.非规格化数:E = 1 - Bias = 1 - 2k-1 - 1;f = M
3.1.非规格化数的范围:小数部分 0 ~ 3/4;阶码值为0,V的范围0 ~ 3/4
开始做题:
a>. 0 00 00: e = 0; E = 1-bias = 0; f = 0; M = 0; V = 0;
b>. 0 00 01: e = 0; E = 0; f = 1/4; M = f = 1/4; V = 1/4 * 2^0 = 1/4
c>. 0 00 10: e = 0; E = 0; f = 2/4; M = f = 2/4; V = 2/4 * 2^0 = 2/4
d>. 0 00 11; e = 0; E = 0; f = 3/4; M = f = 3/4; V = 3/4 * 2^0 = 3/4
e>. 0 01 00(这个就不再是非规格化数了,非规格化数的特点是阶码值全为0,这个符合规格化数):e = 1; E = e - Bias = 1 - 1 = 0; f = 0; M = f + 1 = 4/4; V = 2^0 * 4/4 = 4/4
f>. 0 01 01: e = 1; E = 0; f = 1/4; M = f + 1 = 5/4; V = 2^0 * 5/4 = 5/4
g>. 0 01 10: e = 1; E = 0; f = 2/4; M = f + 1 = 6/4; V = 2^0 * 6/4 = 6/4
h>. 0 01 11: e = 1; E = 0; f = 3/4; M = f + 1 = 7/4; V = 2^0 * 7/4 = 7/4
i>. 0 10 00: e = 2; E = 1; f = 0; M = f + 1 = 4/4; V = 2^1 * 4/4 = 8/4
j>. 0 10 01: e = 2; E = 1; f = 1/4; M = f +1 = 5/4; V = 2^1 * 5/4 = 10/4
k>. 0 10 10: e = 2; E = 1; f = 2/4; M = f +1 = 6/4; V = 2^1 * 6/4 = 12/4
l>. 0 10 11: e = 2; E = 1; f = 3/4; M = f + 1 = 7/4; V = 2^1 * 7/4 = 14/4
m>. 0 11 00 :这种情况就是无穷大的情况,因为阶码值全是1,小数部分全是0
n>. 0 11 01: 这种情况就是NaN了,因为阶码值全是1,而小数部分不全是0(e = 3; E = 2; f = 1/4; M = f + 1 = 5/4; V = 2^2 * 5/4 = 20/4 > 14/4)
三、浮点数舍入
浮点数舍入有四种方法,默认的舍入方法:向偶数舍入(round-to-even),也被称为向最接近的值舍入;其他三种方法产生的实际值的确界;
向偶数舍入:它试图找到最接近的值,采用的方法是将数字向上或者向下舍入,使得结果的最低有效位是偶数
比如:1.5RMB、2.5RMB想偶数舍入的结果都是2RMB
向零舍入:正数向下舍入,负数向上舍入,|x^| <= |x|
向下舍入:把正数和负数都向下舍入,x- < x
向上舍入:吧正数和负数都向上舍入,x+ > x
四、浮点数运算
浮点数不具有结合性
对于任何x,都有NaN + x = NaN
浮点数满足单调性熟属性:a>=b ,对于任何a,b的值,除了x不等于NaN,都有x + a >= x + b
五、浮点数
int、float、double三个类型相互转换:
a>. int转float,数值不会溢出,可能会被舍去
b>. int、float转double,因为double的范围更大,也有更高的位数(更多的有效位),能够保留精确的值
c>.double转float,从大范围转成小范围,所以值可能会溢出成+∞或-∞,由于精度较小,可能会被舍去
d>. double、float转int值将会向0截断,比如1.9999将会等于1,-1.99999将会等于-1
c 浮点数的更多相关文章
- javascript中的浮点数运算
解释一下下面代码的输出 console.log(0.1 + 0.2); //0.30000000000000004 console.log(0.1 + 0.2 == 0.3); //false Jav ...
- 并行计算提升32K*32K点(32位浮点数) FFT计算速度(4核八线程E3处理器)
对32K*32K的随机数矩阵进行FFT变换,数的格式是32位浮点数.将产生的数据存放在堆上,对每一行数据进行N=32K的FFT,记录32K次fft的时间. 比较串行for循环和并行for循环的运行时间 ...
- shell if 浮点数比较
转shell中的浮点数比较http://nigelzeng.iteye.com/blog/1604640 博客分类: Bash Shell shell比较浮点数 由于程序需要,我要判断一个浮点数是否 ...
- PHP浮点数精度问题
这一段时间维护一个类似团购的系统,需要处理订单,也就难免会处理金额 所以有很多PHP的坑 被我狠狠的踩了~~ 首先我们要知道浮点数的表示(IEEE 754): 简言之 就是 埋下了一个大坑 等着你跳 ...
- 关于Linux系统下错误“浮点数异常(核心已转储)”的分析
1.问题发现 有这样一段代码: #include <stdio.h> int main() { int a, b, num1, num2, temp; printf("pleas ...
- C/C++浮点数在内存中的存储方式
一.内存表示 任何数据在内存中都是以二进制的形式存储的,浮点数的表示是把一个数的有效数字和数的范围在计算机的一个存储单元中分别予以表示,数的小数点位置随比例因子的不同而在一定范围内自由浮动.如下图是3 ...
- IEEE 754 浮点数机器表示标准
32位字长浮点数: 共32位 1 8 23 符号位 解码 尾数 0 + 1 - 移127码 原码,隐含小数点前的首位1 不同数据类型之间转换时,隐藏着一些不容易被察觉的错误,比如int 和 un ...
- js,java,浮点数运算错误及应对方法
js,java浮点数运算错误及应对方法 一,浮点数为什么会有运算错误 IEEE 754 标准规定了计算机程序设计环境中的二进制和十进制的浮点数自述的交换.算术格式以及方法. 现有存储介质都是2进制.2 ...
- PHP大数(浮点数)取余
一般我们进行取余运算第一个想到的就是用百分号%,但当除数是个很大的数值,超出了int范围时,这样取余就不准确了. php大数(浮点数)取余函数 /** * php大数取余 * * @param int ...
- 浮点数 (IEEE-754)
浮点数又称"实数",一个浮点数包含三个部分 符号位(S) 阶码 有效数字 S:阶码:有效数字 浮点数是由科学二级制来表示的. 三种类型的浮点数: 短浮点数(32bit): S(b ...
随机推荐
- linux 无外网情况下安装 mysql
由于工作需要,需要在一台装有 CentOS 系统的测试服务器上安装 MySQL ,由于该服务器上存有其他比较重要的测试数据,所以不能连接外网.由于之前安装 MySQL 一直都是使用 yum 命令一键搞 ...
- django 文件上传(阿里云oss)下载(支持大文件下载)
1.文件上传 Models 设计 class Upload_File(models.Model): image = models.FileField(upload_to='file/%Y/%m',de ...
- jdom 插入 修改 删除
创建XML文档 XML文件是一种典型的树形文件,每个文档元素都是一个document元素的子节点.而每个子元素都是一个Element对象,对象可以向下包含. 1 因此我们可以通过先创建元素再将元素添加 ...
- Groovy学习()Groovy是啥?
Groovy是啥? groovy是英文中的一个单词,有marvelous.wonderful和excellen的意思. groovy是轻量级的,动态的,面向对象的,并且运行在JVM上的. groovy ...
- 连接数据库通过配置文件app.config
ConfigurationManager类 public static class ConfigurationManager 命名空间: System.Configuration 程序集: Syste ...
- Android——UI和View——控制方式
控制方式 只用xml实现 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns ...
- 2018-11-17 js的this引起的血案
js的this. 昨天测试,删除商品会报错,马上去测了一把,的确会报错.为毛线呢? SubOrderItem: function (orderitem) { if (orderitem.ordernu ...
- shell向python传参数
想要在shell中调用python脚本时实现: python pyServer.py argu1 argu2 argu3 利用 sys.argv 即可读取到 相应参数: # coding=utf-8 ...
- js获取textaera对象(object)的值
for(i in pstrWord ){ alert(i); //获得属性 alert(pstrWord[i]); //获得属性值 } 1.js输出object对象方法如下: function wri ...
- Android 性能测试之TraceView的使用
Traceview是android平台配备一个很好的性能分析的工具.它可以通过图形化的方式让我们了解我们要跟踪的程序的性能,并且能具体到method. 在SDK路径\tools目录下. 1.在开始使用 ...