C语言中筛选float数组排除-999.9的代码异常及修复方法
问题根源与修复方案
你猜的没错,问题确实出在float的精度特性上。-999.9这个十进制小数无法被float的二进制格式精确存储,实际存进数组的是一个非常接近-999.9的近似值(比如-999.8999938964844),所以直接用nums[i] != -999.9做判断时,因为两边的数值并不严格相等,导致原本要过滤的元素没被过滤掉,最终出现在新数组里。
下面是几种可行的修复方法:
方法1:使用精度阈值比较
通过判断两个浮点数的差值绝对值是否小于一个极小的阈值(比如1e-6),来认定它们“相等”,这样就能避开精度误差的影响:
#include <math.h> // 需要引入math.h来使用fabs函数 float nums[3]={29.34, -999.9, 63.76}; float newn[3]; // 记录新数组的有效元素下标 int idx = 0; for(int i=0; i<3; i++){ // 用差值绝对值判断是否等于-999.9 if(fabs(nums[i] - (-999.9)) > 1e-6){ newn[idx++] = nums[i]; } } // 此时newn的前2个元素是29.34和63.76,idx=2
注意:这里还优化了新数组的存储方式,用单独的下标idx来记录有效元素,避免新数组里出现未初始化的垃圾值(原代码里newn的第二个元素是未赋值的,可能会输出奇怪的数)。
方法2:改用double类型存储
double是双精度浮点数,精度比float高很多,-999.9的近似值会更接近真实值,虽然理论上还是不能精确存储,但在大多数场景下,直接比较的误差会小到可以忽略:
double nums[3]={29.34, -999.9, 63.76}; double newn[3]; int idx = 0; for(int i=0; i<3; i++){ if(nums[i] != -999.9){ newn[idx++] = nums[i]; } }
不过还是更推荐搭配方法1的阈值比较,彻底避免精度问题。
方法3:用精确可表示的整数作为标记值
如果业务场景允许,把-999.9换成一个能被float精确存储的整数(比如-1000),因为整数在float的精度范围内(不超过2^24)可以被精确表示,直接比较就不会有问题:
float nums[3]={29.34, -1000, 63.76}; float newn[3]; int idx = 0; for(int i=0; i<3; i++){ if(nums[i] != -1000){ newn[idx++] = nums[i]; } }
内容的提问来源于stack exchange,提问作者Serban Cociu
相关产品推荐
相关产品推荐

