中文大写数字/金额转化

中文大写数字,规范的写法有这样一些:

二十一

二百二十一

柒仟壹佰零壹

十四万五千

一百一十五万零二十

十二亿六千万

如何将它parse成数字呢?偶使用了递归下降的方法。即,认为它的语法是这样的:

(billion亿)(nt10000万)(nt1000千)(nt100百)(nt10十)(nt1)

其中,billion又可以是:(nt10000万)(nt1000千)(nt100百)(nt10十)(nt1)

nt10000又可以是:(nt1000千)(nt100百)(nt10十)(nt1)

nt1000可以是:(nt100百)(nt10十)(nt1)

以此类推。以下帖出delphi源码:

{ 中文字符串到数字转化
  不支持的格式有: 二二一(数字连写),一万万(非标准进制,应为一亿),二千万亿(超过32位范围) }
function ParseChNumber(const Text: string): Integer;
const
  ChNums: array[1..10] of string = ('一', '二', '三', '四', '五', '六', '七', '八', '九', '十');
  ChNumsBig: array[1..10] of string = ('壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖', '拾');

  function TryGetChNumber(const S: string): Integer;
  var
    I: Integer;
  begin
    if S = '零' then
    begin
      Result := 0;
      Exit;
    end;
    if S = '两' then
    begin
      Result := 2;
      Exit;
    end;
    for I := 1 to 10 do
      if (ChNums[I] = S) or (ChNumsBig[I] = S) then
      begin
        Result := I;
        Exit;
      end;
    Result := -1;
  end;

  type
    TNType = (ntBillion, nt10000, nt1000, nt100, nt10, nt1);

  function ParseN(var S: string; NT: TNType): Integer;
  var
    I: Integer;
    Vals: string;
  begin
    Result := 0;
    if S = '' then Exit;
    if Copy(S, 1, 2) = '零' then S := Copy(S, 3, MaxInt);
    case NT of
      ntBillion:
      begin
        I := Pos('亿', S);
        if I <= 0 then Exit;
        Vals := Copy(S, 1, I - 1);
        S := Copy(S, I + 2, MaxInt);
        Inc(Result, ParseN(Vals, nt10000));
        Inc(Result, ParseN(Vals, nt1000));
        Inc(Result, ParseN(Vals, nt100));
        Inc(Result, ParseN(Vals, nt10));
        Inc(Result, ParseN(Vals, nt1));
        Result := Result * 100000000;
      end;
      nt10000:
      begin
        I := Pos('万', S);
        if I <= 0 then Exit;
        Vals := Copy(S, 1, I - 1);
        S := Copy(S, I + 2, MaxInt);
        Inc(Result, ParseN(Vals, nt1000));
        Inc(Result, ParseN(Vals, nt100));
        Inc(Result, ParseN(Vals, nt10));
        Inc(Result, ParseN(Vals, nt1));
        Result := Result * 10000;
      end;
      nt1000:
      begin
        I := Pos('千', S);
        if I <= 0 then Exit;
        Vals := Copy(S, 1, I - 1);
        S := Copy(S, I + 2, MaxInt);
        // nt100和nt10可去掉,因为没有'X百X十千'的说法
        Inc(Result, ParseN(Vals, nt100));
        Inc(Result, ParseN(Vals, nt10));
        Inc(Result, ParseN(Vals, nt1));
        Result := Result * 1000;
      end;
      nt100:
      begin
        I := Pos('百', S);
        if I <= 0 then Exit;
        Vals := Copy(S, 1, I - 1);
        S := Copy(S, I + 2, MaxInt);
        // nt10可去掉
        Inc(Result, ParseN(Vals, nt10));
        Inc(Result, ParseN(Vals, nt1));
        Result := Result * 100;
      end;
      nt10:
      begin
        I := Pos('十', S);
        if I <= 0 then Exit;
        Vals := Copy(S, 1, I - 1);
        S := Copy(S, I + 2, MaxInt);
        Inc(Result, ParseN(Vals, nt1));
        if Result = 0 then Result := 1;
        Result := Result * 10;
      end;
      nt1:
      begin
        Result := TryGetChNumber(Copy(S, 1, 2));
        if Result < 0 then Result := 0;
        S := Copy(S, 3, MaxInt);
      end;
    end;
  end;

var
  S: string;
begin
  Result := 0;
  S := Text;
  Inc(Result, ParseN(S, ntBillion));
  Inc(Result, ParseN(S, nt10000));
  Inc(Result, ParseN(S, nt1000));
  Inc(Result, ParseN(S, nt100));
  Inc(Result, ParseN(S, nt10));
  Inc(Result, ParseN(S, nt1));
end;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值