一、前言
做 Delphi 业务系统、ERP、金融、交易、支付相关开发时,一定会遇到:
数据库字段:decimal(18,6) 问题:Delphi 端应该用什么类型接收?
网上常见错误答案:
- 用 Double(精度隐患)
- 用 Currency(直接丢数据)
- 很少有人提到真正标准的
TBcd
本文结合实战 + 精度原理,给出最正确、最安全、工业级方案。
二、先明确:decimal (18,6) 是什么?
- 总长度:18 位数字
- 小数固定:6 位
- 要求:绝对精确、不能四舍五入、不能丢位
- 典型场景:金额、费率、汇率、重量、交易金额、第三方接口数据
这种数据绝对不能用不精确类型。
三、致命错误:千万不要用 Currency
很多人被名字误导:
"Currency 是货币类型,存金额最安全!"
大错特错!
Currency 真相
- 固定 4 位小数
- 底层:
Int64 / 10000 - 存入 6 位小数 → 强制四舍五入到第 4 位
示例
plaintext
数据库:123.456789
Currency 存储:123.4568
后两位小数直接丢失,永久无法恢复!
这不是精度问题,是数据损坏。
✅ 结论 :decimal(18,6) 场景 严禁使用 Currency!
四、勉强能用:Double 比 Currency 好,但不推荐
客观事实:Double 确实比 Currency 好很多
原因:
- Double 能保存 15~16 位有效数字
- 不会截断 6 位小数
- 但它是二进制浮点数,天生精度误差
例如:
plaintext
0.1 + 0.2 = 0.3000000000000001
✅ 结论:
- 临时、非核心数据可以用
- 金融、金额、交易、高精度业务 严禁使用
五、正确方案 1:Int64(交易 / 支付 工业标准)
这是你提到的最小单位法,也是微信支付、支付宝、银联、交易接口通用标准:
把数值 ×1000000 用整数存储
示例:
plaintext
123.456789 → 存储为 123456789(Int64)
优点
- ✅ 100% 精确,无任何精度丢失
- ✅ 完美匹配 6 位小数
- ✅ 整数运算极快
- ✅ 跨语言、跨系统无歧义
Delphi 代码模板
delphi
const
SCALE = 1000000; // 6 位小数放大倍数
var
Price: Int64;
begin
// 从数据库读取
Price := Round(DataSet['price'].AsFloat * SCALE);
// 计算(全整数,绝对精确)
Price := Price + 100000; // +0.100000
// 显示
Caption := FormatFloat('0.000000', Price / SCALE);
end;
六、正确方案 2:TBcd(Delphi 官方正统首选)
重点来了!Delphi 原生专门对应数据库 decimal 的精确类型:TBcd
单元:
delphi
Data.FmtBcd
TBcd 是什么?
- 数据库
decimal/numeric的原生内存结构 - 100% 精确十进制
- 支持任意精度(完美支持 18,6)
- 无浮点误差
TBCDField底层就是 TBcd
实战代码
delphi
uses Data.FmtBcd;
var
A, B, C: TBcd;
begin
// 赋值
A := StrToBcd('123.456789');
B := StrToBcd('456.987654');
// 精确运算
C := BcdAdd(A, B); // 加
C := BcdSub(A, B); // 减
C := BcdMul(A, B); // 乘
C := BcdDiv(A, B); // 除
// 显示
Caption := BcdToStr(C);
end;
数据库直接读取(零损耗、最标准)
delphi
var
Value: TBcd;
begin
Value := DataSet['price'].AsBcd;
end;
七、TBcd vs Int64 怎么选?
两个都是 100% 精确 正确方案!
选 TBcd
- 标准业务系统、ERP、管理系统
- 大量数据库操作
- 希望代码最规范、最简单
- 不想手动缩放(×1000000)
选 Int64
- 支付、交易、对接第三方接口
- 跨语言、跨平台
- 追求极致性能
- 习惯最小单位设计
八、终极推荐排名(永不踩坑)
针对 decimal(18,6):
-
🥇 TBcd(Data.FmtBcd) 官方标准、100% 精确、完美匹配→ 业务系统首选
-
🥈 Int64 交易 / 支付标准、极快、精确→ 接口 / 交易系统首选
-
🥉 Double有精度风险,仅临时凑合→ 不推荐用于核心数据
-
❌ Currency 固定 4 位小数,直接丢失 2 位数据→ 绝对禁用
九、总结(金句)
- Delphi 处理
decimal(18,6),只有 TBcd 和 Int64 是正确方案 - Currency 固定 4 位小数,会直接损坏 6 位数据
- Double 有精度隐患,只能算备胎
- 业务系统用 TBcd,交易接口用 Int64
- 固定小数位 = 精确类型 = 行业标准,绝不妥协!
十、结束语
精度问题在金融、交易、金额类系统中是红线问题。希望这篇文章能帮你避开 Delphi 中最常见的数值类型坑。
如果你也在做高精度计算、金额计算、对接支付接口,欢迎点赞、收藏、关注!