CS50 Pset1 Cash贪心算法问题:4.2美元找零计算错误求助
解决CS50找零硬币程序的精度问题
嘿,我一眼就看出你碰到了编程里一个经典的浮点数精度陷阱!这也是很多人刚开始处理货币计算时会踩的坑。
问题根源
你输入4.2美元时,程序输出22而非正确的18,核心原因是float类型无法精确表示所有十进制小数。比如4.2这个数,在二进制浮点数里是一个无限循环的近似值,当你执行change_owed * 100时,得到的并不是精确的420,而是一个非常接近420的数(比如419.999969)。你的循环会把这个值当成比420小一点的数来处理,导致最后多算了好几枚1美分硬币。
另外,你的代码里还有一个小bug:do-while循环的条件里用了未定义的变量c,应该改成判断change_owed < 0才行。
修复方案
解决这个问题的关键是避免用浮点数处理货币单位,转用整数来存储美分。具体可以用round()函数把浮点数转换后的近似值四舍五入到最近的整数,确保得到准确的美分数。
修改后的代码如下:
#include<stdio.h> #include<cs50.h> #include<math.h> // 必须包含math.h才能使用round函数 int main(void) { float change_owed; int change_owed_in_cents; // 用整数存储美分,彻底避免精度问题 int number_of_coins_to_be_given = 0; do { printf("Enter the positive amount of change owed in dollars: "); change_owed = get_float(); } while(change_owed < 0); // 修复未定义变量c的问题 // 用round函数修正浮点数精度误差,再转为整数 change_owed_in_cents = round(change_owed * 100); while(change_owed_in_cents >= 25){ change_owed_in_cents -= 25; number_of_coins_to_be_given++; } while(change_owed_in_cents >= 10) { change_owed_in_cents -= 10; number_of_coins_to_be_given++; } while(change_owed_in_cents >= 5) { change_owed_in_cents -= 5; number_of_coins_to_be_given++; } while(change_owed_in_cents >= 1) { change_owed_in_cents -= 1; number_of_coins_to_be_given++; } printf("%d\n", number_of_coins_to_be_given); }
为什么这样改有效
round()函数会把4.2*100得到的近似值(比如419.999969)四舍五入为准确的420,确保后续计算基于正确的美分数。- 使用整数类型存储美分,后续的减法和比较运算都不会再有精度损失。
- 修复了do-while循环的条件错误,确保只有正数输入才会被接受。
现在再测试4.2美元的情况,程序会正确计算出18枚硬币:16枚25美分+2枚10美分,完美符合最少硬币的要求。
内容的提问来源于stack exchange,提问作者ironman19_
相关产品推荐
相关产品推荐

