我个工具中要用到将数字转人民币大写,百度+ai找到的都多多少少有些问题,然后自己写了一个。支持int64的大数。记录一下。
unit TuaoCustom;
interface
uses system.SysUtils;
//当数字接近于9223372036854775807时(max int64),会存在精度问题
type TAFormat=0..1;
function 取数字字符串的整数和小数部分(const NumStr:string;var IntStr,DecStr:string):boolean;
function 整数转大写(const Number: Int64;AFormat:TAFormat): string;
function 小数转角分(Dec: Integer;AFormat:TAFormat): string;//dec不能大于99
function 金额转人民币大写(const Value: Extended;AFormat:TAFormat): string; //四舍五入到分
function 读数(const Value: Extended;const AFormat:TAFormat): string;
implementation
function 取数字字符串的整数和小数部分(const NumStr:string;var IntStr,DecStr:string):boolean;
var DotCount:byte;str:string;
begin
if NumStr='' then exit(false);
str:=NumStr;
Result:=true;
DotCount:=0;
IntStr:='';DecStr:='';
if not (NumStr[1] in ['-','.','0'..'9']) then
Exit(false);
if NumStr[1]='-' then
begin
if Length(NumStr) = 1 then Exit(False); // :仅 '-' 无效
if NumStr[2]='.' then Exit(False); //如果 -.无效
IntStr:='-';
str:=str.Substring(1); //从第2个字符开始处理
end;
for var ch in Str do
begin
case ch of
'0'..'9':
begin
if DotCount=0 then
IntStr:=IntStr+ch
else
DecStr:=DecStr+ch;
end;
'.':if DotCount=0 then
DotCount:=1
else Exit(False); // 多个小数点错误
else
Exit(false); // 非数字和非小数点字符错误
end;
end;
end;
function 金额转人民币大写(const Value: Extended;AFormat:TAFormat): string;
var
IntPart: Int64;
DecPart: Integer;
IntStr, DecStr: string;
begin
IntPart := Trunc(Value);
DecPart := Round(Frac(Value) * 100);
if IntPart = 0 then
IntStr := '零'
else
IntStr :=整数转大写(IntPart,AFormat);
if DecPart = 0 then
begin
Result := IntStr + '元整';
end
else
begin
Result:=IntStr+'元'+小数转角分(DecPart,AFormat);
end;
end;
function 整数转大写(const Number: Int64;AFormat:TAFormat): string;
const
NumChars: array[0..1] of array[0..9] of string =(('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'),
('零', '一', '二', '三', '四', '五', '六', '七', '八', '九'));
NumChars2:array [0..1] of array [0..2] of string=(('拾','佰','仟'),('十','百','千'));
CN_UNITS: array[0..4] of string = (
'', '万', '亿','兆', '京'
);
var
tempNum: UInt64;
CurrentNum:0..9;
i, len: Integer;
NumStr,str4:string;
StartIndex,level:Integer;
begin
Result:='';
NumStr:='';
tempNum:=Uint64(Abs(Number)); //将负数先转为正数处理
repeat //循环将数字转为汉字,如:123转为壹贰叁
CurrentNum:=tempNum mod 10;
tempNum:=tempNum div 10;
NumStr:=NumChars[AFormat][CurrentNum]+NumStr;
until tempNum=0 ;
level:=0;
repeat StartIndex:=Length(NumStr)-4;
if StartIndex<0 then StartIndex:=0;
str4:=NumStr.Substring(StartIndex,4);
NumStr:=NumStr.Substring(0,StartIndex);
len:=Length(str4);
var s:string:='';
for i := len downto 1 do
begin
if i=len then
begin
if str4[i]<>'零' then
s:=str4[i];
end
else if i=len-1 then
begin
if (str4[i]='零') then
begin
if s<>'' then s:='零'+s;
end
else s:=str4[i]+NumChars2[AFormat][0]+s;
end
else if i=len-2 then
begin
if (str4[i]='零') then
begin
if (s<>'') then
if (s[1]<>'零') then s:='零'+s;
end
else s:=str4[i]+NumChars2[AFormat][1]+s;
end
else if i=len-3 then
begin
if (str4[i]='零') then
begin
if (s<>'') then
if (s[1]<>'零') then s:='零'+s;
end
else s:=str4[i]+NumChars2[AFormat][2]+s;
end
end;
if s<>'' then
s:=s+CN_UNITS[level]
else if (Result<>'') and (Result[1]<>'零') then s:='零';
result:=s+Result;
inc(level);
until Length(NumStr)=0 ;
if Number<0 then Result:='负'+Result; //如果是负数在前面加“负”
end;
function 小数转角分(Dec: Integer;AFormat:TAFormat): string;
const
NumChars: array[0..1] of array[0..9] of string =(('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'),
('零', '一', '二', '三', '四', '五', '六', '七', '八', '九'));
var
Jiao, Fen: Integer;
begin
Result := '';
if Dec=0 then exit;
if Dec < 0 then Dec := 0;
if Dec > 99 then Dec := Dec mod 100;
Jiao := Dec div 10;
Fen := Dec mod 10;
Result := Result + NumChars[AFormat][Jiao] + '角';
if Fen > 0 thenResult := Result + NumChars[AFormat][Fen] + '分';
end;
function 读数(const Value: Extended;const AFormat:TAFormat): string;
const
NumChars: array[0..1] of array[0..9] of string =(('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'),
('零', '一', '二', '三', '四', '五', '六', '七', '八', '九'));
var
IntPart: UInt64;
DecPart: string;
Str, DecStr: string;
DotIndex,Digits :Integer;
begin
IntPart := Trunc(Value);
if IntPart = 0 then
Result := '零'
else
Result :=整数转大写(IntPart,AFormat);
Digits:=25-Length(Format('%d',[IntPart]));
str:=FloatToStrF(Value,ffFixed,25,Digits);// str:=value.ToString;
if Pos('E',str)>0 then exit;
DotIndex:=Pos('.',str);
if DotIndex>0 then
begin
DecStr:='';
DecPart:=Str.Substring(DotIndex);
while (DecPart.Length>0) and (DecPart[DecPart.Length]='0') do //清除小末尾的0
DecPart:=Copy(DecPart,1,DecPart.Length-1);
if (DecPart <>'') and (DecPart<>'0') then
begin
for var i:=1 to Length(DecPart) do
begin
DecStr:=DecStr+numchars[AFormat][StrToInt(DecPart[i])];
end;
Result:=Result+'点'+DecStr;
end
end;
end;
end.
