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

C语言硬币金额换算程序计算错误排查:精度问题求助

硬币金额换算程序的精度问题排查与修复

问题描述

任务是编写程序将金额换算为不同面值的硬币,仅允许使用<stdio.h>、取模和除法操作。

预期输出

Coin     Qty   Balance
-------- --- ---------
              365.5700
Toonies  182    1.5700
Loonies    1    0.5700
Quarters   2    0.0700
Dimes      0    0.0700
Nickels    1    0.0200
Pennies    2    0.0000

实际输出

Coin     Qty   Balance
-------- --- ---------
              365.5700
Toonies  182    1.5700
Loonies    1    0.5700
Quarters   2    0.0600 
Dimes      0    0.0600 
Nickels    1    0.0100
Pennies    1    0.0000

原代码

#include <stdio.h>

int main() {
    
    double total = 365.5700;
    
    int toonies, loonies, quarters, dimes, nickels, pennies;
    double balToonies, balLoonies, balQuarters, balDimes, balNickels, balPennines;
    
    // Toonies
    toonies = (int)total / 2;   
    balToonies = (int)(total * 100) % 200 / 100.0;
   
    // Loonies
    loonies = (int)balToonies / 1;
    balLoonies = (int)(balToonies * 100) % 100 / 100.0;
    
    // Quarters
    quarters = (int)(balLoonies * 100) / 25;
    balQuarters = (int)(balLoonies * 100) % 25 / 100.0;
   
    // Dimes
    dimes = (int)(balQuarters * 100) / 10;
    balDimes = (int)(balQuarters * 100) % 10 / 100.0;
    
    // Nickels
    nickels = (int)(balDimes * 100) / 5;
    balNickels = (int)(balDimes * 100) % 5 / 100.0;
    
    // Pennies
    pennies = (int)(balNickels * 100) / 1;
    balPennines = (int)(balNickels * 100) % 1 / 100.0;
   
    printf("Coin     Qty   Balance\n");
    printf("-------- --- ---------\n");
    printf("%22.4lf\n", total);
    printf("Toonies  %3d %9.4lf\n", toonies, balToonies);
    printf("Loonies  %3d %9.4lf\n", loonies, balLoonies);
    printf("Quarters %3d %9.4lf\n", quarters, balQuarters);
    printf("Dimes    %3d %9.4lf\n", dimes, balDimes);
    printf("Nickels  %3d %9.4lf\n", nickels, balNickels);
    printf("Pennies  %3d %9.4lf\n\n", pennies, balPennines);
    
    return 0;
}

问题根源

核心问题是浮点数精度误差。double类型无法精确表示所有十进制小数,比如365.57在二进制浮点数中是一个无限循环的近似值,实际存储的值略小于365.57。当执行(int)(balLoonies * 100)时,balLoonies是0.57的近似值,乘以100后得到的是接近57但略小于57的数,强制转换为int后就变成了56,后续所有计算都因此出错。

修复方案

全程使用整数处理,将金额转换为以分为单位的整数,彻底避免浮点数精度问题。所有硬币面值也统一用分来表示:

  • Toonies:200分
  • Loonies:100分
  • Quarters:25分
  • Dimes:10分
  • Nickels:5分
  • Pennies:1分

修正后的代码

#include <stdio.h>

int main() {
    // 将金额转换为以分为单位的整数,避免浮点数误差
    int total_cents = 36557;
    
    int toonies, loonies, quarters, dimes, nickels, pennies;
    int balance;
    
    // 初始余额为总分数
    balance = total_cents;
    
    // Toonies(200分)
    toonies = balance / 200;
    balance = balance % 200;
    
    // Loonies(100分)
    loonies = balance / 100;
    balance = balance % 100;
    
    // Quarters(25分)
    quarters = balance / 25;
    balance = balance % 25;
    
    // Dimes(10分)
    dimes = balance / 10;
    balance = balance % 10;
    
    // Nickels(5分)
    nickels = balance / 5;
    balance = balance % 5;
    
    // Pennies(1分)
    pennies = balance;
    balance = 0;
    
    // 格式化输出,将分数转换回元显示
    printf("Coin     Qty   Balance\n");
    printf("-------- --- ---------\n");
    printf("%22.4lf\n", total_cents / 100.0);
    printf("Toonies  %3d %9.4lf\n", toonies, (total_cents % 200) / 100.0);
    printf("Loonies  %3d %9.4lf\n", loonies, (total_cents % 200 % 100) / 100.0);
    printf("Quarters %3d %9.4lf\n", quarters, (total_cents % 200 % 100 % 25) / 100.0);
    printf("Dimes    %3d %9.4lf\n", dimes, (total_cents % 200 % 100 % 25 % 10) / 100.0);
    printf("Nickels  %3d %9.4lf\n", nickels, (total_cents % 200 % 100 % 25 % 10 % 5) / 100.0);
    printf("Pennies  %3d %9.4lf\n\n", pennies, 0.0);
    
    return 0;
}

代码说明

  1. 用total_cents存储总金额的分数(365.57元 = 36557分),完全避免浮点数操作。
  2. 每一步计算硬币数量时,用整数除法得到数量,取模得到剩余余额(分数)。
  3. 输出时将分数转换回元(除以100.0),保证显示格式符合要求。

这样计算出来的结果完全符合预期输出,不会出现精度误差。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 14:55:22