zoukankan      html  css  js  c++  java
  • 部分数值存储误差问题

     1 /*
     2 * 
     3 *  test the accuracy change of conversion from float to dobule 
     4 *
     5 */
     6 public class TestFloat{
     7 
     8     public static void main(String[] args){
     9             float f1 = 2.2f;
    10             System.out.printf("before conversion float1 :  %10.9f \n" , f1);
    11             float f3 = f1;
    12             double d1 = (double)f1;
    13             System.out.printf("after conversion double1 : %10.9f \n" , d1);
    14             float f2 = 2.25f;
    15             System.out.printf("before conversion float2 :  %10.9f\n" , f2);
    16             double d2 = (double)f2;
    17             System.out.printf("after conversion double2 : %10.9f \n" , d2);
    18     }
    19 }
    20 /*
    21 
    22     result :
    23     
    24     before conversion float1 :2.2
    25     after conversion double1 :2.200000047683716
    26     before conversion float2 :2.25
    27     after conversion double2 :2.25
    28     
    29     problom :
    30     
    31     'f1' value hava been changed when output.  
    32     
    33     reason : 
    34     
    35     the binary repersentation of 2.2f is :  00110011001100110011... 
    36     
    37     (is an infinite recurring decimal)
    38     
    39     but computer only store 24 byte , so discard the remaining number , lead to the value has been change .
    40 
    41 */

    从上面我们可以看出,向计算机中存入float类型的数值2.2 后,在输出会出现数值发生了变化,在注释中我已经说明了问题和导致这个问题的原因,由于我的英语有待提高,所以在这再重复一遍:

    问题:

    当向计算机中存入一个float类型的数值2.2 后,在从计算机中读出输出,这时2.2 的值已经发生了变化。

    原因:

    要将浮点数值2.2存入计算机中,要进过下面几个步骤:

    --》机器将2.2 转换成二进制形式。整数位2即是10,小数部分就不同了,根据乘2取整法计算0.2的二进制表示你会发现它是一个无限循环数--0011 0011 0011……,所以2.2 的二进制表示为: 10.0011 0011 0011 …… 。

    --》将2.2的表示转换成科学计数法  即 : 1.0 0011 0011 0011 …… X 2^1

    --》存储 , 浮点数计算机中分配的存储容量为32个字节(不知道是不是所有的语言或者所有的计算机都是这样,待以后更正),分配情况为:

          符号位     1

          指数位     8

          尾数位    23

      但是在科学计数法下,尾数的首数值一定是1,所以第一位不存储,这样就能为float增加一位精度,为24位。2.2 的存储如下:

          符号位   : 0(表示正)

          指数位   :采用移位存储,元数据为127 ,所以该部分应该存储 127 + 1 ,即128 : 1000 0000

          尾数位   : 因为尾数位只有24位,所以要截取无限循环小数部分的前24位,注意 : 截取造成了数值的改变。

    根据尾数位的存储便可发现,计算机中2.2 的存储已经发生了变化,而且存储的值比2.2 要大,主要是存储的小数部分要比0.2 要大。具体原因可以算一下。因为小数部分转换成十进制每位要乘以10^(-X),当小数部分的位数减小,那么相应的X要减小,由于是X前面有个 - 号,所以值就变大了。

    上面提供的是Java代码,同样在C语言中也是这样:

    1 #include <stdio.h>
    2 int main(){
    3     float f1 = 2.2 ;
    4     printf("%10.9f",f1);
    5     return 0;
    6 }

  • 相关阅读:
    Oracle删除.dbf文件报错
    Java 7 新的 try-with-resources 语句,自动资源释放
    模式对话框提交form之后总是打开新的页面
    MyEclipse更改项目的发布目录
    IntelliJ IDEA 更换发布目录
    java.sql.SQLException: ORA-00942: 表或视图不存在
    编码那点事
    配置nginx实现windows/iis应用负载均衡
    MSMQ消息队列
    .NET 分布式技术比较
  • 原文地址:https://www.cnblogs.com/caiyao/p/3661627.html
Copyright © 2011-2022 走看看