中文大写数字,规范的写法有这样一些:
二十一
二百二十一
柒仟壹佰零壹
十四万五千
一百一十五万零二十
十二亿六千万
如何将它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;