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

C语言ATM开发:不使用浮点数实现货币小数乘法的方案

不用浮点数实现货币兑换的解决方案

你的核心问题是用整数除法存储汇率导致精度丢失——91/100在C语言整数运算里结果是0(并非你说的1),所以乘以任何数都得0,自然无法得到正确结果。完全可以不用浮点数解决这个问题,核心思路是用整数表示汇率的比例值,把所有金额转换成最小货币单位(比如分)来做整数运算,具体步骤如下:

1. 修正汇率的存储方式

直接存储汇率的分子(避免整数除法):

  • 美元转欧元的0.91,存成91(代表91/100)
  • 美元转英镑的0.79,存成79
  • 欧元转美元的1.10,存成110
  • 英镑转美元的1.27,存成127

修改后的变量定义:

// 汇率表示:分子/100,比如UStoEU=91 → 0.91
int UStoEU_ExchangeRate = 91;
int UStoUK_ExchangeRate = 79;
int EU_US_ExchangeRate = 110;
int UK_US_ExchangeRate = 127;

2. 统一用最小单位(分)计算

货币计算的关键是把所有金额转换成以分为单位的整数,比如$10.50就是1050美分,€8.25就是825欧分。这样所有运算都是整数操作,完全没有精度损失。

针对你的Currency结构体,写两个辅助函数处理单位转换:

// 把Currency的main和frac转换成总分数
int get_total_cents(struct Currency c) {
    // 可额外加判断,确保frac是0-99的合法值
    return c.main * 100 + c.frac;
}

// 把总分数拆回Currency的main和frac
void set_from_total_cents(struct Currency *c, int total_cents) {
    c->main = total_cents / 100;
    c->frac = total_cents % 100;
    // 处理负分的情况(比如计算后出现负值)
    if (c->frac < 0) {
        c->main -= 1;
        c->frac += 100;
    }
}

3. 修正兑换计算逻辑

修改你的兑换函数,让它处理完整的货币结构体(而不只是main部分):

// 将Banka(美元)转换成Dinero指定的货币,结果存入Dinero
void convert_currency() {
    int us_total = get_total_cents(Banka);
    int target_total;

    if (strcmp(Dinero.symb, "$") == 0) {
        target_total = us_total;
    } else if (strcmp(Dinero.symb, "E") == 0) {
        // 加50是为了四舍五入到分,避免截断误差
        target_total = (us_total * UStoEU_ExchangeRate + 50) / 100;
    } else if (strcmp(Dinero.symb, "P") == 0) {
        target_total = (us_total * UStoUK_ExchangeRate + 50) / 100;
    } else {
        // 未知货币,默认返回0
        target_total = 0;
    }

    set_from_total_cents(&Dinero, target_total);
}

4. 其他关键细节

  • 你的Currency结构体中symb[1]存在内存越界风险:字符串需要末尾的\0结束符,所以至少要定义成char symb[2],否则strcmp会读取非法内存。修改后:
    struct Currency {
        int main;
        int frac;
        char symb[2]; // 存储"$"、"E"、"P"及结束符
    };
    
  • 若允许用户修改汇率,可让用户输入小数后转换成分子(比如输入0.91,乘以100取整存为91);或直接让用户输入分子值(比如输入91代表0.91)。
  • 避免整数溢出:如果处理大额金额,建议用long代替int,比如把total_cents定义为long类型,防止运算时超出int的范围。

为什么不能用浮点数?

浮点数(float/double)的二进制存储无法精确表示所有十进制小数,比如0.1在二进制里是无限循环小数,多次计算后会累积精度误差,而货币计算要求分毫不差,因此必须用整数运算保证精确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:52:31