C语言浮点数各种情况下的进位问题

苦于浮点数的折磨,写个帖子总结下各种情况的浮点数进位问题。

一、正常输出时进位情况

        1、float类型变量

          

float a;
scanf("%f,&a");
printf("%.xf",a);//x为整数,即小数位数

        当输入a的小数位数小于x,a大小不变,精度为x

        当输入a的小数位数大于x,若为x小于6,从x+1位四舍五入,x等于6,从x+n(n>1)位四舍五入(x小于等于6)。注:当x大于6时,由于浮点数存储的误差,对输出值的影响不能确定!

        eg:1.000-->1.000000(x为6)

                1.1236-->1.124(x为3)

                1.12346-->1.123(x为3)

                1.11111149-->1.111112(x为6)

        2、double类型变量

        同float

        本质上输出时的进位情况是由浮点数在计算机中存储值的大小决定的

        eg.0.3的二进制为0.0100110011001100110011001100110011001100110011001101

                再转换成十进制为0.300000011920928955078125

                这样就产生了精度误差

二、强制类型转换   

         double  f  =  3.456;

         int i = (int)(f * 100)+ 0.5)  /  100;           

        使用强制转换直接把小数部分切割掉

        但有时可能会出现存储时的不精确进而影响类型转换时值。

       eg:9.99999999999在储存中为10.000000001,这时强制转换就会变成10,产生四舍五入的错觉。

三、输出时的隐式强制类型转换

   比如想下面这样的代码

double a;
scanf("%lf",&a);
printf("%d",a);

        这样要出大问题,比如输入1.1,输出却是-1717986918,非常的amazing。

        这是因为整型是以二进制补码的形式存储的,可以精确表示,存储的就是数值。但是浮点数不一样,浮点数是以编码的形式存储的,不是直接存储数值,而且有精度问题,浮点数是以“符号位+阶码+尾数”的形式存储。float类型符号位占1位,阶码占8位,尾数占23位,总共32位;double类型符号位占1位,阶码占11位,尾数占52位。所以说,如果printf在输出时,因为格式字符是“%d”,所以它会以整型的方式去解析浮点数的编码。将浮点数编码直接当做二进制补码来计算数值,就会出现上面的结果。

        来量化分析一手:比如浮点数的编码为0 000 1000 0000 000 0011 0011 0011 0011 0011 0011 1111 0011 0111 0011 0001 0011 0,这里的第1个0表示符号,在这里是正数,接下来的11位表示阶码,这里表示130(3+127)。后面的52位表示尾数,而从int类型的视角来看,都是2的次方位。此外,由于int和double的大小不同,8字节的double会被4字节的int阶段,进而错上加错。

        所以安全的方法是加上显式强制类型转换。

未完待续。。。。。。

                

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值