You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

beecrowd 1021:输入576.73时金额转分计算异常问题

Beecrowd 1021题:输入576.73时分币计算错误问题

这段C语言代码在处理多数金额时能正常输出纸币和硬币的数量,但输入576.73时,分币(R$ 0,01)的计算结果会出错。

原代码

#include <stdio.h>
#include <math.h>
 
int calculo(float num);

int main() {
 
    float numero;
    
    scanf("%f",&numero);

    calculo(numero);

    return 0;
}

int calculo(float num) {

    //TRANSFORMA PARA INTEIRO
    int n;
    //NOTAS 
    int n100, n50, n20, n10, n5, n2;
    //MOEDAS 
    int m1, m05, m025, m010, m005, m001;

    //NOTAS
    n = floor(num);

    n100 = n/100;
    n50 = (n%100)/50;
    n20 = ((n%100)%50)/20;
    n10 = (((n%100)%50)%20)/10;
    n5 = ((((n%100)%50)%20)%10)/5;
    n2 = (((((n%100)%50)%20)%10)%5)/2;
    
    //MOEDAS 
    m1 = (((((n%100)%50)%20)%10)%5)%2;
    
    n = num*100;
    n = (int) n*1;
    
    n = n%100;
    m05 = n/50;
    n = n%50;
    m025 = n/25;
    n = n%25;
    m010 = n/10;
    n = n%10;
    m005 = n/5;
    m001 = n%5;

    printf("NOTAS:\n");
    printf("%d nota(s) de R$ 100,00\n",n100);
    printf("%d nota(s) de R$ 50,00\n",n50);
    printf("%d nota(s) de R$ 20,00\n",n20);
    printf("%d nota(s) de R$ 10,00\n",n10);
    printf("%d nota(s) de R$ 5,00\n",n5);
    printf("%d nota(s) de R$ 2,00\n",n2);
    
    printf("MOEDAS:\n");
    printf("%d moeda(s) de R$ 1,00\n",m1);
    printf("%d moeda(s) de R$ 0,50\n",m05);
    printf("%d moeda(s) de R$ 0,25\n",m025);
    printf("%d moeda(s) de R$ 0,10\n",m010);
    printf("%d moeda(s) de R$ 0,05\n",m005);
    printf("%d moeda(s) de R$ 0,01\n",m001);

    return 0;
}

问题原因

核心是浮点数精度丢失:
float属于单精度浮点数,无法精确表示所有十进制小数(比如576.73)。当执行num*100时,实际计算结果是57672.999999...而非精确的57673,强制转换为int类型时会直接截断小数部分,得到57672,后续分币计算就会少1个0.01的硬币。

修复方案

方案1:用round()函数四舍五入

修改处理小数部分的关键代码,先对num*100的结果四舍五入,再转换为整数:

// 替换原来的n = num*100; n = (int) n*1;
n = round(num * 100); // 四舍五入后得到精确的分数值

方案2:改用double类型提升精度

将float替换为double,再配合四舍五入,能进一步减少精度问题:

// main函数中把float numero改为double numero
double numero;
scanf("%lf", &numero);

// calculo函数的参数也改为double
int calculo(double num) {
    // ...
    n = round(num * 100);
    // ...
}

方案3:直接读取整数形式的金额

如果输入格式允许,可以直接读取以分为单位的整数,完全避免浮点数运算:

// 比如输入57673代表576.73雷亚尔
int numero;
scanf("%d", &numero);

修复后的完整代码示例

#include <stdio.h>
#include <math.h>
 
int calculo(double num);

int main() {
 
    double numero;
    
    scanf("%lf",&numero);

    calculo(numero);

    return 0;
}

int calculo(double num) {

    int n;
    int n100, n50, n20, n10, n5, n2;
    int m1, m05, m025, m010, m005, m001;

    // 处理纸币部分
    n = floor(num);

    n100 = n/100;
    n50 = (n%100)/50;
    n20 = ((n%100)%50)/20;
    n10 = (((n%100)%50)%20)/10;
    n5 = ((((n%100)%50)%20)%10)/5;
    n2 = (((((n%100)%50)%20)%10)%5)/2;
    
    m1 = (((((n%100)%50)%20)%10)%5)%2;
    
    // 处理硬币部分,修复精度问题
    n = round(num * 100);
    n = n%100;
    m05 = n/50;
    n = n%50;
    m025 = n/25;
    n = n%25;
    m010 = n/10;
    n = n%10;
    m005 = n/5;
    m001 = n%5;

    printf("NOTAS:\n");
    printf("%d nota(s) de R$ 100,00\n",n100);
    printf("%d nota(s) de R$ 50,00\n",n50);
    printf("%d nota(s) de R$ 20,00\n",n20);
    printf("%d nota(s) de R$ 10,00\n",n10);
    printf("%d nota(s) de R$ 5,00\n",n5);
    printf("%d nota(s) de R$ 2,00\n",n2);
    
    printf("MOEDAS:\n");
    printf("%d moeda(s) de R$ 1,00\n",m1);
    printf("%d moeda(s) de R$ 0,50\n",m05);
    printf("%d moeda(s) de R$ 0,25\n",m025);
    printf("%d moeda(s) de R$ 0,10\n",m010);
    printf("%d moeda(s) de R$ 0,05\n",m005);
    printf("%d moeda(s) de R$ 0,01\n",m001);

    return 0;
}

内容的提问来源于stack exchange,提问作者Henrique Bispo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 05:55:00