zoukankan      html  css  js  c++  java
  • 三:计算机进行小数运算时出错的原因

    0、开篇:

    (1)二进制数0.1,用十进制数表示的话是多少?
         0.5
    (2)用小数点后有3位的二进制数,能表示十进制数0.625吗?
         可以,0.101
    (3)将小数分为符号、尾数、基数、指数4部分进行表现的形式称为什么?
         浮点数(浮点数形式)
    (4)二进制数的基数是什么?
         2
    (5)通过把0作为数值范围的中间值,从而在不使用符号位的情况下来表示负数的表示方法称为什么?
         EXCESS系统表示(EXCESS是“剩余的”的意思。例如,把01111111看作是0的话,比这个数小1的01111110就是-1)
    (6)10101100.01010011这个二进制数,用十六进制数表示的话是多少?
         AC.53

    1、将0.1累加100次也得不到10

    2、用二进制数表示小数

      先来一个热身,把1011.0011这个有小数点的二进制数转换成十进制数(前面章节已经讲过了用二进制来表示整数的方法,其实小数也一样),如下图所示:

      

    3、计算机运算出错的原因

       通过第2节的学习,大家应该也能大概知道计算机运算出错的原因了:是因为“有一些十进制数的小数无法转换成二进制数”。例如十进制数0.1,就无法用二进制数正确表示,小数点后面即使有几百位也无法表示。

          我们就看小数点后4位用二进制数表示时的数值范围0.0000~0.1111,如下图所示:

      

      这里只能表示0.5 、 0.25 、 0.125 、0.0625这四个二进制数小数点后面的位权组合而成(相加总和)的小数。再回到我们要表示的0.1,怎么加都无法加到0.1的,只会变成0.00011001100...(1100的循环),不信你可以去试试。

           说到这里,大家应该都能明白为什么将0.1累加100次也得不到10的原因了把,因为无法正确表示的数值,最后都变成了近似值。计算机是一个功能有限的机器设备,是无法处理无限循环的小数的,一般计算机都会从中间截断。

    4、什么是浮点数

      像1011.0011这样带小数点的表现形式,完全是纸面上的二进制数表现形式,在计算机内部是无法使用的。这一章节主要是说明计算机是以什么样的表现形式来处理小数。很多编程语言中都提供了两种表示小数的数据类型,分别是双精度浮点数与单精度浮点数。双精度浮点数类型用64位、单精度浮点数用32位来表示全体小数。从C语言中,双精度浮点数类型和单精度浮点数类型分别用double和float来表示。

      浮点数是指符号、尾数、基数和指数这四个部分来表示的小数,如下图:

      

      因为计算机内部使用的是二进制,所以基数自然就是2.因此,实际的数据中往往不考虑基数,只用符号、尾数、指数这三部分即可表示浮点数。也就是说,64位(双精度浮点数)和32位(单精度浮点数)的数据,会被分为三部分来使用,如下图展示:

      

      ① 符号部分:是指使用一个数据位来表示数值的符号。该数据位是1时表示负,为0时则表示“正或者0”。
         ② 尾数部分:数值大小的决定部分之一(另外一个是指数部分)。尾数部分用的是“将小数点前面的值固定为1的正则表达式”。
         ③ 指数部分:用的则是EXCESS系统表现。

    5、正则表达式和EXCESS系统

       ① 尾数部分使用正则表达式,可以将表现形式多样的浮点数统一为一种表现形式。例如十进制的0.75就有很多种表现形式:

       

          正因为表现形式太多,计算机处理时就会比较麻烦。因此,为了方便计算机处理,需要制定一个统一的规则。例如,十进制数的浮点数应该遵循“小数点前面是0,小数点后面第1位不能是0”这样的规则。根据这个规则,0.75就是“0.75 * 10的0次幂”,也就是说,只能用尾数部分是0.75、指数部分是0这个方法来表示。根据这个规则来表示小数的方式,就是正则表达式。
         二进制数也是同样的道理,在二进制数中,我们使用的是“将小数点前面的值固定为1的正则表达式”。具体来讲,就是将二进制数表示的小数左移或右移(这里是逻辑移位。因为符号位是独立的)数次后,正数部分的第1位变为1,第2位之后都变为0(这样是为了消除第2位以上的数位)。而且,第1位的1在实际的数据中不保存。由于第1位必须是1,因此,省略该部分后就节省了一个数据位,从而也就可以表示更多的数据范围。
    下图是单精度浮点数的正则表达式的具体例子(单精度浮点数中,尾数部分是23位):

      

    6、在实际的程序中进行确认

      对EXCESS系统与正则表达式了解了吗,如果还没有了解,就返回上一小节再看一看,我也是看了几遍才看懂的,如果看懂了,就往下看,用C语言程序来确认单精度浮点数表示方法。

    7、如何避免计算机计算出错 

       计算机计算出错的原因之一是采用浮点数来处理小数(另外,也有因“位溢出”而造成计算错误的情况)。作为程序的数据类型,不管是使用单精度浮点数还是双精度浮点数,都存在计算出错的可能性。接下来会介绍两种避免该问题的方法。
         ① 回避策略,即无视这个错误,只要得到近似值就可以了,那些微小的误差完全可以忽略掉。
         ② 把小数转换成正数来计算。

    8、二进制数和十六进制数 

       最后补充说明一下二进制数和十六进制数的关系。在实际程序中,如果二进制位数太多,看起来会比较麻烦,因此,在实际程序中,也经常会用十六进制数来代替二进制数。二进制数的4位,正好相当于十六进制数的1位。例如,32位二进制数00111101110011001100110011001101用十六进制数来表示的话,就是3DCCCCCD这个8位数。由此可见,通过使用十六进制数,二进制数的位数能够缩短至原来的1/4 。
         用十六进制数来表示二进制小数时,小数点后的二进制数的4位同样相当于十六进制的1位。不够4位时用0填补二进制数的低位即可。例如,1011.011的低位补0后为1011.0110,这时就可以表示为十六进制数B.6 。
     
  • 相关阅读:
    flink 读取kafka 数据,partition分配
    Flink 报错 "Could not find a suitable table factory for 'org.apache.flink.table.factories.StreamTableSourceFactory' in the classpath"
    flume接收http请求,并将数据写到kafka
    【翻译】Flume 1.8.0 User Guide(用户指南) Processors
    【翻译】Flume 1.8.0 User Guide(用户指南) Channel
    【翻译】Flume 1.8.0 User Guide(用户指南) Sink
    【翻译】Flume 1.8.0 User Guide(用户指南) source
    【翻译】Flume 1.8.0 User Guide(用户指南)
    Apache Flink 简单安装
    Java之使用IDE
  • 原文地址:https://www.cnblogs.com/Helius/p/7256986.html
Copyright © 2011-2022 走看看