在计算 220 % 25 的余数为 20 而 420 % 25 的余数为 19 时计算余数的不一致? [复制]

Posted

技术标签:

【中文标题】在计算 220 % 25 的余数为 20 而 420 % 25 的余数为 19 时计算余数的不一致? [复制]【英文标题】:Inconsistencies when calculating the remainder where 220 % 25 gives a remainder of 20 while 420 % 25 gives a remainder of 19? [duplicate] 【发布时间】:2020-08-01 12:09:08 【问题描述】:

作为 CS50 课程的一部分,我们的任务是创建一个程序(用 C 语言),根据用户提交的值计算最少的硬币数量(0.25 美元、0.10 美元、0.05 美元和 0.01 美元)。

我的想法是取输入值乘以 100 并使用整数,因为唯一感兴趣的值是硬币的数量而不是货币价值,因此我不必修改任何小数。

代码是:

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

int main(void)

    //If it's NOT a positive number, do this.
    float n;
    do
    
        n = get_float("Change owed: \n");
    
    while (n <= 0);

    //Multiplying change owed with 100 to avoid having to deal with decimals.
    int cash = n * 100;

    //Calculating the number of quarters ($0.25).
    int quarters = cash / 25;                           //How many full quarters per cash.
    int quarters_rem = cash % 25;                       //The remainder after full amout of quarters in cash.
    printf("Number of quarters: %i\n", quarters);       //Test how many quarters.
    printf("Remainder: %i\n", quarters_rem);            //Test how much remainder.

    //Calculating the number of dimes ($0.10).
    int dimes = quarters_rem / 10;                      //How many full dimes from the remainder when all quarters are deducted.
    int dimes_rem = round(quarters_rem % 10);           //The remainder after full amount of dimes in quarters_rem.
    printf("Number of dimes: %i\n", dimes);             //Test how many dimes.
    printf("Remainder: %i\n", dimes_rem);               //Test how much remainder.

    //Calculating the number of nickels ($0.05).
    int nickels = dimes_rem / 5;                        //How many full nickels from the remainder when all dimes are deducted.
    int nickels_rem = round(dimes_rem % 5);             //The remainder after full amount of nickels in dimes_rem.
    printf("Number of nickels: %i\n", nickels);         //Test how many nickels.
    printf("Remainder: %i\n", nickels_rem);             //Test how much remainder.

    //Calculating the number of cents ($0.01).
    int cents = nickels_rem;                            //How many full cents from the remainder when all nickels are deducted.
    printf("Number of cents: %i\n", cents);             //Test how many nickels.

    //Prints the least number of coins to be returned.
    int coins = quarters + dimes + nickels + cents;
    printf("%i\n", coins);

问题是,当我运行代码并输入 2.2、6.2 或 8.2 时,在计算四分之一后,输出给我的余数是 20。 2.2 x 100 = 220 -> 25 x 8 = 200,如预期的那样,余数为 20。 2.2、6.2、8.2、10.2、12.2、14.2 等都是如此。

但是,如果我进入 4.2,这不是!真的!如果我输入 4.2 我期望: 4.2 x 100 = 420 -> 25 x 16 = 400 这应该给我 20 的余数,但我得到了 19 的余数?我不明白为什么在这种情况下余数是 19 而在其他情况下是 20?

【问题讨论】:

底线是:永远不要使用“普通”浮点类型来赚钱。有人会赔钱。 它应该解释一切:godbolt.org/z/Pq4Tjj @AdrianMole 有人会松,有人会赚钱。如果您是赢家,请使用花车:) int cash = n * 100; 截断乘积 - 不完全是 420。使用 long cash = lround(n * 100.0); 得到最近的一分钱而不是截断。 【参考方案1】:

浮点的典型实现以二进制格式存储数字,因此它不能精确存储一些十进制数字。

有了这个程序

#include <stdio.h>

int main(void) 
    float x = 4.2;
    float y = x * 100;
    printf("%.10f\n", y);
    return 0;

I got output:

419.9999694824

这表明4.2f * 100 变得比420 略小,将其转换为int 将导致419 而不是420

为避免这种情况,在这种情况下,您应该在将float 转换为int 之前添加较小的值。

int cash = n * 100 + 0.1;

【讨论】:

以上是关于在计算 220 % 25 的余数为 20 而 420 % 25 的余数为 19 时计算余数的不一致? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

列表内列表之间的欧几里得距离

用C语言编写(计算两个整数的和、 差、积、商与余数

58进制转换工具

微信小程序data数据获取问题

220V和380V电器设备电流计算方法

算数运算符