前几天,有个小伙伴在作实验过程当中,发现了一个奇怪的现象,这个现象就是…ui
他在用printf输出浮点数的时候,想把数据保留到小数点后的两位,他是这么写的…spa
float c=1.155;printf(“%.2f”,c);调试
他的书写是对的,没有错误。可是他发现,当c等于1.555时,保留两位小数输出是1.55,而当c等于3.555时,保留两位小数输出是3.56。这个结果,就让人捉摸不透了,由于…开发
若是是程序运算会自动四舍五入的话,结果应该是1.56和3.56;若是程序运算不会自动四舍五入的话,结果应该是1.55和3.55。但是结果倒是1.55和3.56,这是什么鬼?产品
若是你去百度输入关键词“浮点数 四舍五入”,你会发现,有些人会说浮点数会自动四舍五入,以下图…io
而有些人会说,不会自动四舍五入,以下图…class
到底会不会自动四舍五入呢?基础
我刚才拿老顽童STM32开发板作了一个实验,我定义了6个浮点数,他们分别是…变量
而后我用printf给他们保留2位小数后输出,程序以下…原理
在串口调试助手上看到的结果是…
结果是,6个数,有3个数自动四舍五入了,有3个数没有四舍五入。
无论理论是什么,咱们只看结果。结果是:浮点数保留小数点后的数据,有时会自动四舍五入,有时不会自动四舍五入。可是…
若是把一个浮点数赋给一个整数变量后,必定不会四舍五入。
因此,咱们在保留浮点数的小数点精度时,必需要人工处理四舍五入。
不少人一直在用的一个的方法,就是加0.5法。
这个方法的理论依据是:
float f;//定义了一个浮点数
int t;//定义了一个整数
咱们执行(t=f;)这条语句,无论f的小数点后面是小于5的数,仍是大于等于5的数,都不会四舍五入,例如当f=3.2和f=3.8,结果都是t=3。
那么怎么样让f=3.8时,t=4呢?咱们能够给f+0.5来解决,例如当f=3.8时,f+0.5=4.3,执行完t=f后,t就等于4了。而当f的小数点后的的数都小于5时,加一个0.5不会大于4,因此执行完t=f后,结果还都是3。这正好符合咱们四舍五入的要求。
这里须要注意的是:其实这个…
加0.5的方法
只适合用于保留整数位的应用
不少人都不知道这一点,下面我就给你们实践一下。
按照加0.5法的原理,若是要保留2位有效数据的话,须要给数据加0.005,咱们作个实验,把temp1~6都加0.005。
而后咱们看输出结果,以下图…
看到了正确的结果,你不要高兴,由于…
你如今能够把temp1~6的小数点后面都改成554,以下图…
这时候,正确的结果,小数点后两位应该都是55,可是你看看结果,仍是照样是56。这时候,就输出了彻底错误的结果。
有的朋友会说,既然加0.005不行,那咱们想办法仍是加0.5吧。好的,下面我有一个方法…
先把temp1*100,而后再+0.5,而后把这个浮点数赋值给一个整数,而后再把这个整数除以100。
例如temp5的程序写为…
temp5=temp5*100+0.5;
t5=temp5;
temp5=(float)t5/100;
其中,t5是我定义的一个uint32_t类型的整型变量。咱们来分析一下,由于temp5=4.555,4.555乘以100之后是455.50,而后再加0.5之后是456.00,把456.00取整后是456,而后456除以100就是4.56。
一切都算计的很好,可是实际的结果却仍是4.55。可是若是你这样写的话,结果就是正确的…
temp5=4.555*100+0.5;
t5=temp5;
temp5=(float)t5/100;
看这个程序和上边的程序对比一下,只是这里直接用了4.555,而上边的程序用了temp5,看似同样,结果却不同。上边程序的结果是4.55,下边程序的结果是4.56。
上边两个加0.5的实践,你必定要试一下。
那保留2位小数,怎么作才能确保彻底正确?
送给你们一句话:捷径有多是歧途,最笨的办法,实际上是最保险的办法。(顽童哥语录必定要收藏)
咱们能够把小数点后的第三位数取出来,而后判断它和5的大小,而后四舍五入。就是这个方法,绝对正确。写成程序的话,是这个样子的…
其中,t1是定义的uint32_t类型的整型变量。咱们把数据带进去看一下,temp1是0.555,0.555乘以1000是555,555除以100取余数是55,55再除以10取余数是5,那t1就等于5。下面用if语句判断是否要进位,若是须要进位的话,4.555乘以100就是455.5,455.5加1就是456.5,而后咱们把456.5强制类型转换成整型数据,就是456,456除以100,就是4.56;若是不须要进位的状况,你们自行分析。
这时候,你去换temp1~6的值去吧,无论换什么,结果都会四舍五入。
作一个稳定的电子产品,基础知识很重要!