C语言统计double类型小数点后位数运行结果异常求助
问题根源
你遇到的问题本质是二进制浮点数的精度局限性:double类型采用IEEE754标准存储,无法精确表示绝大多数十进制小数(比如你用的10.123,实际存储的是接近10.123的近似值,不是完全相等的),随着你每次乘10的操作误差不断累积,就会出现你观察到的异常现象:
- 本该是3.0的数实际存储为2.999999999999999,modf取整数部分就得到2而不是3
- 本该是0的小数部分实际存储为非常接近1的数值,导致判断
f!=0永远成立,最后循环了50次才因为精度耗尽停止
原代码的现存问题
- 局部变量f没有初始化就直接作为while循环的判断条件,属于未定义行为,运行结果不可预测
- 直接用
f!=0判断浮点数是否为0是错误做法,浮点数计算存在天然误差,几乎不会出现严格等于0的情况 - 没有考虑误差累积的影响,每次乘10的操作会放大之前的精度误差,导致整数部分取值错误
修正后的代码
#include <math.h> #include <stdio.h> int main() { double integer_part; double fractional_part; int count = 0; double num = 10.123; // 精度阈值,小于这个值就认为小数部分为0,可根据实际需求调整精度 const double eps = 1e-9; // 先拆分一次再进入循环,避免变量未初始化问题 fractional_part = modf(num, &integer_part); while(fractional_part > eps){ count = count + 1; num = fractional_part * 10; fractional_part = modf(num, &integer_part); // 可选:打开注释打印过程方便调试 // printf("第%d位:整数部分%lf,剩余小数部分%lf\n", count, integer_part, fractional_part); } printf("Count = %d", count); return 0; }
额外建议
如果你的需求是精确统计十进制数字的小数位数,完全避免浮点数精度问题,更推荐的做法是直接将输入作为字符串读取,找到小数点的位置后统计小数点之后的字符个数即可,这种方法完全不会有精度误差。
内容的提问来源于stack exchange,提问作者Anastay Kaiser
相关产品推荐
相关产品推荐

