在Delphi中,为了实现货币数值运算中的严格精度要求,内部把货币类型数据当作一个放大10000倍的64位整数来处理。这样根据64位整数的范围,可以得出货币类型Currency的范围是 [-922337203685477.5807; 922337203685477.5807]。

货币类型一个最常见的应用场景是金额大写转换,网上都是一些先将货币转字符串后再对字符串处理的代码,而且有些方法在有些情况下不满足金额大写规范,这里给出一个直接转换的方法。

unit TU2.Helper.Currency;interfacefunction CurrencyToChineseCapitalCharacter(const AValue: Currency; const ADecimals: Cardinal=4): string;
function CurrencyToString(const AValue: Currency; const ADecimals: Cardinal=4): string;implementationuses System.SysUtils, System.Math;function CurrencyRound(var U: UInt64; const ADecimals: Cardinal): Integer; inline;
varW: UInt64;
begin//Bankers-roundingResult := 4-ADecimals;if Result<0 thenResult := 0else if Result>0 thenbegincase Result of1:begin   //liDivMod(U, 10, U, W);if (W > 5) or ((W = 5) and Odd(U)) thenInc(U);end;2:begin  //fenDivMod(U, 100, U, W);if (W > 50) or ((W = 50) and Odd(U)) thenInc(U);end;3:begin  //jiaoDivMod(U, 1000, U, W);if (W > 500) or ((W = 500) and Odd(U)) thenInc(U);end;4:begin  //yuanDivMod(U, 10000, U, W);if (W > 5000) or ((W = 5000) and Odd(U)) thenInc(U);end;end;end;
end;function CurrencyToChineseCapitalCharacter(const AValue: Currency; const ADecimals: Cardinal=4): string;
const//Currency: [-922337203685477.5807, 922337203685477.5807]CCCNegative = '负';CCCZheng = '整';CCCNumbers: array[0..9] of Char = ('零','壹','贰','叁','肆','伍','陆','柒','捌','玖');CCCUnits: array[0..18] of Char = ('毫', '厘', '分', '角', '元','拾','佰','仟','万','拾','佰','仟','亿','拾','佰','仟','万','兆','拾');
varU, W: UInt64;Digits, Idx, ZeroFlag: Integer;Negative: Boolean;Buff: array[0..38] of Char;
beginU := PUInt64(@AValue)^;if U <> 0 thenbeginNegative := (U and $8000000000000000) <> 0;if Negative thenU := not U + 1;Digits := CurrencyRound(U, ADecimals);if U<>0 thenbegin//Try skip trailing zerorepeatDivMod(U, 10, U, W);Inc(Digits);until W<>0;Dec(Digits);Idx := 38;if Digits>=3 thenbeginBuff[Idx] := CCCZheng;Dec(Idx);if Digits>4 thenbeginBuff[Idx] := CCCUnits[4];Dec(Idx);if Digits>17 thenbeginBuff[Idx] := CCCUnits[17];Dec(Idx);end else if Digits>12 thenbeginBuff[Idx] := CCCUnits[12];Dec(Idx);end else if Digits>8 thenbeginBuff[Idx] := CCCUnits[8];Dec(Idx);end;end;end;Buff[Idx] := CCCUnits[Digits];Dec(Idx);Buff[Idx] := CCCNumbers[W];Dec(Idx);//Do SplitZeroFlag := 0;while U<>0 dobeginInc(Digits);DivMod(U, 10, U, W);if Digits in [4,8,12,17] thenbeginif ZeroFlag>0 thenbeginBuff[Idx] := CCCNumbers[0];Dec(Idx);end else if (ZeroFlag<0) and (Digits>8) thenInc(Idx);Buff[Idx] := CCCUnits[Digits];Dec(Idx);if W<>0 thenbeginBuff[Idx] := CCCNumbers[W];Dec(Idx);ZeroFlag := 0;end elseZeroFlag := -1;end else beginif W<>0 thenbeginif ZeroFlag>0 thenbeginBuff[Idx] := CCCNumbers[0];Dec(Idx);end;Buff[Idx] := CCCUnits[Digits];Dec(Idx);Buff[Idx] := CCCNumbers[W];Dec(Idx);ZeroFlag := 0;end else beginif ZeroFlag=0 thenZeroFlag := 1;end;end;end;if Negative thenBuff[Idx] := CCCNegativeelse Inc(Idx);//Copy ResultDigits := 38+1-idx;SetLength(Result, Digits);Move(Buff[idx], PChar(Result)^, Digits * SizeOf(WideChar));Exit;end;end;Result := CCCNumbers[0]+CCCUnits[4]+CCCZheng;
end;function CurrencyToString(const AValue: Currency; const ADecimals: Cardinal=4): string;
constNegativeChar = '-';DecimalDotChar = '.';
varU: UInt64;Digits: Integer;Negative: Boolean;
beginU := PUInt64(@AValue)^;Negative := (U and $8000000000000000) <> 0;if Negative thenU := not U + 1;Digits := CurrencyRound(U, ADecimals);Result := UIntToStr(U);if Digits<4 thenResult := Result.Insert(Result.Length+Digits-4, DecimalDotChar);if Negative thenResult := NegativeChar + Result;
end;end.

对上面两个方法进行最大货币数值测试,并与自带货币转字符串方法比较。

64位结果如下:

32位结果如下:

注:耗时采用高精度计时器测量,应忽略突兀数值看平均值。

从对比上可以看出在64位程序下,这个方法性能要好于系统自带转换方法,而且其中文大写转换跟字符串转换性能一样。但在32位系统下,性能却差一点,这是因为这个方法主要采用了DivMod方法进行整除取余操作获取每位的数字,该方法在32位程序下,当被除数大于32位正整数时,其采用循环减10实现整除取余,这种情况下循环次数非常大。

附: 金额大写规范

一、人民币大写金额数字到“元”为止的,在“元”之后,应写“整”(或“正”)字;在“角”之后,可以不写“整”(或“正”)字;大写金额数字有“分”的,“分”后面不写“整”(或“正”)字。
二、阿拉伯数字小写金额数字中有“0”时,人民币大写应按照汉语语言规律。举例如下:
1. 阿拉伯金额数字中间有“0”时,人民币大写要写“零”字。如¥1409.50,应写成人民币陆壹仟肆佰零玖元伍角。
2. 阿拉伯金额数字中间连续有几个“0”时,人民币大写金额中间可以只写一个“零”字。如¥6007.14,应写成人民币陆仟零柒元壹角肆分。
3. 阿拉伯金额数字万位和元位是“0”;或者数字中间连续有几个“0”,万位(或元位)也是“0”,但千位(或角位)不是“0”时;中文大写金额中可以只写一个零字,也可以不写“零”字。如¥1680.32,应写成人民币壹仟陆佰捌拾元零叁角贰分或者写成人民币壹仟陆佰捌拾元叁角贰分。又如¥107000.53,应写成人民币壹拾万柒仟元零伍角叁分或者写成人民币壹拾万零柒仟元伍角叁分。
4. 阿拉伯金额数字角位是“0”,而分位不是“0”时,中文大写金额“元”后面应写“零”字。如¥16409.02,应写成人民币壹万陆仟肆佰零玖元零贰分,又如¥325.04.应写成人民币叁佰贰拾伍元零肆分。

Delphi货币类型转中文大写金额相关推荐

  1. ASP.NET C# 货币转换函数 中文大写金额 英文金额

    // 静态中文转换方法     String GetCnString(String MoneyString) // 最大转化金额         9999999999999999.99  (16位整数 ...

  2. 使用函数_使用TEXT函数生成中文大写金额

    为满足<中华人民共和国票据法>中对中文大写金额的书写要求,可以使用TEXT函数将数字格式转换为中文大写金额.图中A列是小写的金额,需要在B列使用公式将其转换为中文大写金额. 生成中文大写金 ...

  3. 项目中中文大写金额的工具类

    关于中文大写,网上有很多代码可以下载使用,但是仔细看了,很多都不完美支持财务要求的中文大写规则,以前好像看到过中文大写类库,但是不记得了,于是只好自己写 财务规则: 零在元位和万位上时,这个零一般可写 ...

  4. 【Java】将阿拉伯数字金额转化为中文大写金额表示

    今天老师即兴布置了一个作业,将阿拉伯数字金额转化为中文大写金额表示,假设数字上限为小于10亿,可以支持2位小数,如: 100000001--壹亿零壹元整 100100011--壹亿零壹拾万零壹拾壹元整 ...

  5. 处理发票上的中文大写金额的转换工具类

    处理发票中数字金额转成中文大写金额字符串问题. 效果图: package com.szmsd.hulutianxia.util;public class ChineseNumberUtil {publ ...

  6. java实现数字金额转换中文大写金额

    直接贴代码吧! public class CnNumberUtils {private final static Logger logger = LoggerFactory.getLogger(CnN ...

  7. c#金额转换成中文大写金额

    c#金额转换成中文大写金额 原文:c#金额转换成中文大写金额 2018-08-24 转别人 c#金额转换成中文大写金额 /// <summary>/// 金额转换成中文大写金额/// &l ...

  8. 37 CO配置-控制-产品成本控制-成本对象控制-实际成本核算/物料分类帐-分配货币类型并定义物料分类账类型

    业务背景:分配货币类型并定义物料分类账类型 事务码: OMX2 SPRO路径:SPRO->控制->产品成本控制->实际成本核算/物料分类帐->分配货币类型并定义物料分类账类型 ...

  9. 11 FI配置-财务会计-定义分类账和货币类型的设置

    业务背景:定义分类账和货币类型的设置 事务码: SPRO SPRO路径:SPRO->财务会计->财务会计全局设置->分类账->分类账->定义分类账和货币类型的设置 第1步 ...

  10. [原创]数字转换中文大写金额

    [原创]数字转换中文大写金额 程序需要:2控件: text1 command1 command1下代码: On Error Resume Next If InStr(Text1, ".&qu ...

最新文章

  1. 二叉树遍历的递归、非递归方法(前序、中序、后序,层序)——Java实现
  2. MYSQL查看执行计划 Explain
  3. 安卓 camera 调用流程_安卓如何做出微信那样的界面仿微信“我”的界面1/5
  4. 被指涉嫌“二选一” 山姆回应:欢迎良性竞争
  5. qemu模拟器下编译运行基于riscv指令集的Linux操作系统
  6. 自然语言处理--中文文本向量化counterVectorizer()
  7. VS C# 中使用番茄助手
  8. 手机php文件怎么修改,安卓手机上pdf文件怎么修改
  9. 使用HTML语言和CSS开发商业站点_利用CSS3制作网页动画
  10. Amlogic Linux系列(四) 视频解码分析2
  11. 服务器系统咋关机呀,服务器关机详细步骤
  12. 揭密win7pe制作全过程
  13. 流年祭.掩埋一场与青春有关的荒芜
  14. Android无法通过浏览器观看HLS直播的问题
  15. NOMSQL数据库之Mongodb
  16. flex布局——最后一行左对齐的实现方式(css功能实现)
  17. 救活被微软封杀的Windows XP操作系统(转)
  18. ETH-TRUNK(链路汇聚技术)
  19. CISSP第4/8知识点错题集
  20. 2023年北京科技大学通信考研上岸前辈备考经验指导

热门文章

  1. 2021年微信视频号生态趋势调查报告|友望数据发布
  2. EXCEL 中数据分析常用统计方法介绍(一)
  3. asp big5 gb2312 转 Unicode
  4. Linux安全模块(LSM)
  5. Linux进程之如何查看进程详情?
  6. eliminate什么意思_eliminate是什么意思_eliminate在线翻译_英语_读音_用法_例句_海词词典...
  7. 明道云实现产品BOM清单的快速搭建
  8. 计算机毕设应用型开题报告,毕设开题报告范文.doc
  9. android离线身份证识别(从相册选择)
  10. 关于手心输入法配置完整自然码辅码