【问题标题】:Small bug in my short C code. Why?我的简短 C 代码中的小错误。为什么?
【发布时间】:2012-10-29 19:50:01
【问题描述】:

我不明白为什么这对 90% 的输入有效,而对其他输入无效。它的目的是告诉你有多少硬币可以换回来。大多数测试金额都可以正常工作,但如果您输入 4.20(或 4.20 美元),它会返回 23 个硬币……应该是 18 个硬币(16 个硬币和 2 个镍币)。错误在哪里?这是我的代码:

#include <stdio.h>
#include <cs50.h>

int main(void){

    float change = 0.00;

    printf("How much change is owed? ");
    change = GetFloat();

    float quarters = change/.25;
    change-= (int)quarters*.25;

    float dimes = change/.10;
    change-= (int)dimes*.10;

    float nickels = change/.05;
    change-= (int)nickels*.05;

    float pennies = (change+.005)/.01;
    change-=(int)pennies*.01;

    int total = (int)quarters+(int)dimes+(int)nickels+(int)pennies;

    printf("%d\n", total);

    return 0;
    }

【问题讨论】:

  • 你不应该首先使用浮点数来表示金钱。
  • 既然一切都是 1 美分的倍数,为什么不将一切都存储为整数美分呢?这样您就可以避免所有与浮点相关的麻烦。
  • 这是一个家庭作业,应该教授浮点功能,这是它按原样编写的唯一原因。奇怪的是大多数输入都可以正常工作,只有某些数字不能。我不能用不同的类或任何东西重写它,因为这是教授希望看到的方式。
  • 一切都不是 1 美分的倍数
  • @kallikak 在问题中命名一个不是...的货币值?

标签: c floating-point cs50


【解决方案1】:

4.20 最接近的float 值略小于(4.19999980926513671875,对于通常的 32 位 IEEE754 floats)。因此,从 16 个季度中减去 4 美元后,剩下的金额略小于 0.2。除以 0.1 得到的值略小于 2,因此您的 nickels 值为 1。同样的情况在减去镍后,值略小于 0.1,除以 0.05 得到的商略小于2.

你应该只在这样的计算中使用整数,以美分计算。

【讨论】:

  • 在 Objective-C 中,NSDecimalNumber 类也是一种选择,但会更麻烦。
  • +1 表示准确的 IEEE 值。你是手工计算还是从网站计算的?
  • 我让我的 Haskell 解释器计算,fromRational 将有理数转换为最接近的可表示浮点数。
  • 提醒我拿其中一个(计算器)。我的朋友称是个书呆子.. =P
【解决方案2】:

抛出浮点计算。这完全基于百分之一,所以只需使用整数除法/模数。 从不依赖浮点数的完美准确性。

#include <stdio.h>
#include <cs50.h>

int main(void){

    float fchange = 0.00;
    int change = 0;

    printf("How much change is owed? ");
    fchange = GetFloat();

    change = (int)roundf(fchange*100.0);

    int quarters = change/25;
    change = change % 25;

    int dimes = change/10;
    change = change % 10;

    int nickels = change/5;
    change = change % 5;

    printf("%d quarters, %d dimes, %d nickels, %d pennies\n", quarters, dimes, nickels, change);

    return 0;
}

【讨论】:

  • change = (int)(fchange * 100.0);
  • @DanielFischer 谢谢丹尼尔。当我发布这篇文章时,我完全是在回答一个不同的问题(手指)。
  • 多任务处理?我希望我能做到。
  • @DanielFischer 自从我使用花车以来就一直如此。你想帮我检查一下吗?谢谢。
  • floor 是错误的。你可以在乘以 100 之后 floor,但如果所有输入都是非负的,则不需要(如果可能有负输入,则需要像 floor 这样的东西)。不过我会使用change = (int)roundf(fchange*100);
【解决方案3】:

其他答案大多涵盖:您应该在这里使用定点,而不是浮点。但是,从浮点输入到定点表示时,请小心正确舍入。这是我破解的一个简短版本,它应该适用于所有积极的输入:

#include <stdlib.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
    float change = atof(argv[1]);
    int work = (int)(100*change+0.5);
    int quarters, dimes, nickels, pennies;
    quarters = work/25; work %= 25;
    dimes    = work/10; work %= 10;
    nickels  = work/5;  work %=  5;
    pennies  = work;
    printf("%.2f dollars = %d quarters, %d dimes, %d nickels and %d pennies: %d coins total\n",
    change, quarters, dimes, nickels, pennies, quarters+dimes+nickels+pennies);
    return 0;
 }

例如:

./change 4.20
4.20 dollars = 16 quarters, 2 dimes, 0 nickels and 0 pennies: 18 coins total

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-27
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    相关资源
    最近更新 更多