C语言浮点数精度问题:找零程序计算出错如何锁定小数位
根因说明
你遇到的问题确实由浮点数精度问题导致:
- 0.1、0.05、0.01这类十进制小数无法通过二进制浮点数精确存储,实际存储值会和理论值存在微小误差,比如0.1可能存储为0.099999994,做减法比较时就会出现预期外的结果。
- 你代码中还有两个额外bug加重了异常:1. 硬币面值数组里的镍币面值写错为0.5,正确应为0.05;2. 没有对数组下标i做边界判断,当剩余金额小于1分时i会持续递增,越界访问内存导致输出乱码、程序卡死。
最优修复方案
核心思路是将所有金额转换为以分为单位的整数运算,完全规避浮点数精度问题,修改点如下:
- 输入金额后直接转换为整数分,加微小偏移量解决浮点数转整数的截断误差
- 所有硬币面值统一改为以分为单位的整数值
- 增加数组下标边界判断,避免越界访问
- 完善负数输入的校验逻辑,支持用户重新输入
修改后完整代码:
#include <stdio.h> #include <cs50.h> int main (void) { // 完善输入校验,要求用户必须输入正数 float number; do { number = get_float("Number: "); if (number < 0) { printf("A positive number, Please: \n"); } } while (number < 0); // 转成以分为单位的整数,加1e-6避免浮点数截断误差 int total_cents = (int)(number * 100 + 1e-6); // 硬币面值统一为分单位整数 int coinValues[] = {100, 25, 10, 5, 1}; char *coinNames[] = {"Dollar(s): ", "Quarter(s): ", "Dime(s): ", "Nickel(s): ", "Penny(ies): "}; int i = 0; int tmp = 0; int coin_count = sizeof(coinValues) / sizeof(coinValues[0]); // 硬币种类总数,用于边界判断 while (total_cents > 0 && i < coin_count) { if (total_cents >= coinValues[i]) { printf("%s", coinNames[i]); tmp = 0; while (total_cents >= coinValues[i]) { total_cents -= coinValues[i]; tmp++; } printf("%i\n", tmp); } else { i++; } } return 0; }
验证效果
输入2.6时,转换为整数是260分,计算逻辑为:
- 260 / 100 = 2个Dollar,剩余60分
- 60 / 25 = 2个Quarter,剩余10分
- 10 / 10 = 1个Dime,剩余0分直接结束循环,完全符合预期。
内容的提问来源于stack exchange,提问作者Will Felipe
相关产品推荐
相关产品推荐

