C语言计算浮点数的小数位数,屏蔽掉了浮点运算的误差
来源:互联网 发布:ubuntu怎么稳定翻墙 编辑:程序博客网 时间:2024/04/30 01:16
问题是这样的,输入两个浮点数,分别为矩形的width和length,求其面积area,并输出显示。本身这道题是没什么好说的,正常来说,只要 %f 就好,虽然后面的小数位数恒定为6位。但是答题后发现答案是会自动把多余的0去掉的,这样的话就没办法使用%.3f之类的来限定具体的小数位数了。于是这个就需要我们把结果area算出具体的的小数位数n,使用printf("%.*f",n,area);来显示含正确小数位数的浮点数area。
因为一下子没想出来怎么计算小数位数,故而百度之类的搜索了一下,网上流传的的方法,从原理上来讲貌似没有错。找到的方法基本原理都是这样的,对浮点数f*10,然后判断个位数是否非0,如果非0则小数位数n++,直到个位为零,则n为该浮点数f的小数位数。
这里面其实是有两个问题的,导致他没有办法计算出正确的小数位数,甚至出现死循环的现象。
其中问题为:
1.上面的方法没有考虑到小数点后面的数中间含有0的现象,比如说2.120056,这样的话,如果用上述的方法,则会计算出小数位数为2,因为在计算到第位小数时为零,故而退出n的循环。
(这里面网上是有解决方法的,方法为 f - (int)f > (float)0.000001是否成立,若成立,则小数位数已计算完毕,若不成立,则继续循环。但是这种方法依然会产生下面的2的问题,从而无法结束循环,得不到正确的结果);
2.上面的方法没有考虑到浮点数的相乘是会产生误差的,比如,
f = 2.123456;
s = f*10 ;// 结果为21.234560
s =s*10;//结果为212.2345603
这时就出现了误差0.000003,故而会使程序无法结束循环。
于是思考好久之后,有了以下这种我的解决方法。
首先,我们是知道浮点型float的小数位数是为6位的,所以我们只要一开始就假定area是有6位小数,然后再逆转判断。具体程序如下:
int float_n(float area)
{
int n = 6;//一开始就假定小数位数为6位
long temp = (int)area * 1000000;//将6位小数全部取出,并舍弃计算后多余的可能是误差的小数部分
for(n = 6; n>0 ;i--)
{
if( 0 != temp %10 ) break;
temp = temp/10;
}
return n;
}
此时,n就是正确的小数位数了。
printf(" area = %.*f \n" , n , area);
可以正确显示去除多于的零的area结果了。
目前我在思考第二种有效的方法,大家知道,所有的数据都是按照二进制存储在内存中的,那么我们是否可以进行位运算 操作,来直接从float的储存格式获得小数的位数呢?
- C语言计算浮点数的小数位数,屏蔽掉了浮点运算的误差
- 获得一个浮点数的小数位数
- 截取浮点数的小数位数
- 关于浮点数的运算误差问题
- 浮点数的误差
- 浮点数的误差
- C语言printf(""),浮点数打印保留有效位数,小数部分的四舍五入
- C语言详解 之 浮点数的表示误差
- C语言中浮点数的运算
- 浮点数的精确误差
- JavaScript中浮点数的保留小数位数的问题
- 一种浮点数控制小数位数的方法
- 计算时使用浮点数产生误差的原因分析
- C语言中浮点数的表示方法---浮点数表示引起的误差---IEEE 754关于浮点数的规定
- 1.浮点数运算误差
- 浮点数的运算
- 浮点数的运算
- C语言 字符串的浮点数转换成浮点数
- Java Runtime.exec 调用linux SCP 命令Copy 远程机器上的目录失败
- 通用线程:POSIX 线程详解,第 2部分
- 通用线程:POSIX 线程详解,第 3 部分
- [LeetCode] Divide Two Integers
- hdoj 2674 N!Again 【同余定理】+【找规律】
- C语言计算浮点数的小数位数,屏蔽掉了浮点运算的误差
- js数组的操作
- BING objectness 代码运行 vs2012 64位
- HDU 1087 && POJ 2533(DP,最长上升子序列).
- php学习路线
- 【IIS】windows2003 iis6.0站点打不开,找不到服务器或 DNS 错误
- Pager-taglib分页使用
- POJ 3114 Countries in War 强连通tarjan缩点后 跑最短路spfa
- 数据结构学习笔记4