前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >深入理解计算机系统(2.7)------浮点数舍入以及运算

深入理解计算机系统(2.7)------浮点数舍入以及运算

作者头像
IT可乐
发布2018-01-04 14:55:29
2.5K0
发布2018-01-04 14:55:29
举报
文章被收录于专栏:IT可乐IT可乐

  上一篇博客我们讲解了二进制小数如何表示以及IEEE浮点标准。而且我们也提到过因为这种表示方法限制了浮点数的范围和精度,浮点数只能近似的表示一个数。

  比如 数字1/5,我们能用十进制小数 0.2 准确的表示,但是我们却不能把它准确的表示为一个二进制小数,我们只能通过增加二进制表示的长度来提高表示的精度。如下:

  那我们该怎么办呢?

1、舍入

  对于不能精确的表示的数,我们采取一种系统的方法,找到“最接近”的匹配值,它可以用期望的浮点形式表现出来,这就是舍入。

舍入一共有四种方式,分别是向偶数舍入、向零舍入、向上舍入以及向下舍入

  可以看下面的例子:

   向偶数舍入,是将数字向上或向下舍入,使得结果的最低有效数字是偶数;而向零舍入则是向靠近零的值舍入;向上舍入则是向比它大的方向靠近;向下舍入则是向比它小的方向靠近。

  这四个我们可以用一个直角坐标系来理解:

  除了向偶数舍入以外,其它三种方式都会有明确的边界。这里的含义是指这三种方式舍入后的值x'与舍入之前的值x会有一个明确的大小关系,比如对于向上舍入来说,则一定有x <= x'。对于向零舍入来说,则一定有|x| >= |x'|。

  那么我们什么时候会使用向偶数舍入呢?

  1、比如舍入一组数值,计算这些值的平均数中引入统计偏差,如果向上舍入,那么得到的平均值会比这些数本身的平均值略高;向下舍入,则会偏低。而向偶数舍入则会避免这种偏差,在50%的时间内,它向上舍入,剩下50%的时间内,它向下舍入。

  2、在我们不想舍入到整数时,我们只是简单的考虑最低有效数字是奇数还是偶数。

通常情况下我们采取的舍入规则是在原来的值是舍入值的中间值时,采取向偶数舍入,在二进制中,偶数我们认为是末尾为0的数。而倘若不是这种情况的话,则一般会有选择性的使用向上和向下舍入,但总是会向最接近的值舍入。其实这正是IEEE采取的默认的舍入方式,因为这种舍入方式总是企图向最近的值的舍入。

 2、浮点运算

   在IEEE标准中,制定了关于浮点数的运算规则,就是我们将把两个浮点数运算后的精确结果的舍入值,作为我们最终的运算结果。正是因为有了这一个特殊点,就会造成浮点数当中,很多运算不满足我们平时熟知的一些运算特性。

  我们可以先看下面这段程序输出结果:

代码语言:javascript
复制
public void testFloat(){
		float f1 = 3.14f + 10000000000f - 10000000000f;
		float f2 = 3.14f + (10000000000f - 10000000000f);
		System.out.println(f1);
		System.out.println(f2);
		
	}

  结果都是 3.14 吗?

  我们看到 f1 的值是0,f2的值才是3.14。为什么呢?这是因为前面3.14f+10000000000f  时,会将 3.14 这个有效数值舍入掉,而导致最终结果为0.0

  f2 由于括号的存在,会先进行括号里面的运算,结果是0,然后在与3.14相加。

  也就是浮点运算不满足加法的结合律 a + b + c != a + (b + c)。同时乘法结合律也不满足:a * b * c != a * (b * c);还要分配律也不满足: a * (b + c) != a * b + a * c

  浮点数失去了很多运算方面的特性,因此也导致很多优化手段无法进行,比如我们试图优化下面这样一段程序。

代码语言:javascript
复制
/*   优化前       */
        float x = a + b + c;
        float y = b + c + d;
        /* 编译器试图省去一个浮点加法      */
        float t = b + c;
        float x = a + t;
        float y = t + d;

  上面优化前是进行了四次浮点运算,而编译器优化后只需要进行三次浮点运算。但是这中间的 x 可能回产生与原始值不同的值,因为它使用了加法运算不同的结合方式。所以现在的编译器都倾向于保守的方式,避免任何对功能产生的优化,即使是很轻微的影响。

  另外,浮点加法满足单调性属性:如果 a>=b,那么对于任何a、b以及 x 的值,除了 NaN,都有 x+a >= x+b。无符号或者补码加法不具有这个实数(和整数)加法的属性。

 3、总结

   好了,那么到此《深入理解计算机系统》前面两章的内容我们就结束了,这里我们主要需要了解无符号和补码编码格式,以及它们的运算。然后扩展到整数的表示和运算,实数的表示和运算,在实际编程中,我们会经常和数打交道,如何避免一些错误,相信看完后会有个大概的了解了。那么接下来我们将学习第三章,这将是一个全新的世界——汇编语言。这肯定比我们前面讲的要有趣多了,前面都是和0或者1这样的数字打交道,后面至少是一种编程语言,相信会更加有趣。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-09-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、舍入
  •  2、浮点运算
  •  3、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档