中文大寫數字/金額轉化

中文大寫數字,規範的寫法有這樣一些:

二十一

二百二十一

柒仟壹佰零壹

十四萬五千

一百一十五萬零二十

十二億六千萬

如何將它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;

發佈了41 篇原創文章 · 獲贊 2 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章