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

Delphi中Trunc处理Currency数值出现精度偏差的原因咨询

Delphi中Currency类型数值拆分的精度问题分析

先看你的代码:

var
  StrNum: string;
  CurDecimalNum: currency;
  Amount : currency;
begin
    Amount := 1868.45;
    StrNum := FormatFloat('00', trunc(frac(Amount) * 100));   // 返回44
    CurDecimalNum := frac(Amount) * 100;                      //Patch7
    StrNum := FormatFloat('00', trunc(CurDecimalNum));         // 返回45
end.

问题根源:类型转换带来的精度差异

  • Currency是定点数类型:它内部以64位整数存储,精度固定为4位小数,所以1868.45在内存中是精确的18684500(每个单位对应0.0001)。
  • frac函数返回Extended浮点数:调用frac(Amount)时,Currency类型的Amount会被隐式转换为Extended浮点数。而0.45无法用二进制浮点数精确表示,实际存储的是一个略小于0.45的值。
  • 一行式计算的截断问题:frac(Amount)*100在Extended域计算后,结果是略小于45的数(比如44.9999999999999...),trunc函数直接截断小数部分,得到44。
  • 拆分两行的修复逻辑:当把计算结果赋值给Currency类型的CurDecimalNum时,Currency的定点数特性会自动将这个略小于45的浮点数四舍五入到4位小数精度,也就是45.0000。此时trunc得到45,FormatFloat返回正确结果。

更稳妥的写法

如果要避免这类问题,建议直接利用Currency的定点数特性拆分,比如:

var
  IntegerPart: Integer;
  DecimalPart: Integer;
  Amount: Currency;
begin
  Amount := 1868.45;
  IntegerPart := Trunc(Amount);
  DecimalPart := Round((Amount - IntegerPart) * 100);
  // 或者简化:DecimalPart := Round(Frac(Amount) * 100);
end;

用Round代替Trunc,或者先通过Currency类型中转,都能规避浮点数精度带来的截断问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 15:17:20