- 注册时间
- 2007-9-1
- 最后登录
- 1970-1-1
|

楼主 |
发表于 2009-12-16 21:48:30
|
显示全部楼层
其实这个函数速度较慢,
文曲星上转换“一十九亿九千九百九十九万九千九百九十九”=1999999999
要0.26秒
又用C写了个,几乎完全注释:
#define MAX 16 //最大位数
char _NUMBER[59]="零一壹二贰三叁四肆五伍六陆七柒八捌九玖十拾廿百佰千仟万兆亿";
double _Num(double *num,char *wei,char len)//各位对应数字,位,位数
{//递归辅助函数
double i, a, tmp;//临时数字
int w;//位数指针
char c;//指针
w = len - 1;
while(w>0)//逆序检测单位顺序是否由大到小,如“五千万五千”的单位顺序就不是由大到小
{
if(*(wei+w-1) <= *(wei+w))//前一个单位小于或等于后一个单位
{
c = w;//记录后一单位
w--;
while(*(wei+w-1)<=*(wei+c) && w)//检索到前一个单位大于记录单位为止
w--;
*(num+w) = _Num(num+w,wei+w,c-w) + *(num+c);//递归赋值
len = len - c + w;//长度收缩
for(char x=w+1;x<len;x++)//合并各位对应数值
*(num+x) = *(num+x+c-w);
for(x=w;x<len;x++)//合并位
*(wei+x) = *(wei+x+c-w);
}
w--;
}
a = 0;//临时计算用数
c = 0;
while(c<len)//计算
{
tmp = *(num+c);
switch(*(wei+c))
{
case 10: i = 10;break;
case 11: i = 20;break;
case 12: i = 100;break;
case 13: i = 1000;break;
case 14: i = 10000;break;
case 15: i = 1000000;break;
case 16: i = 100000000;break;
default : i = 1;
}
if(tmp)
a = a + i*tmp;
else
if(*(wei+c))
a = a + i;//将单位转换为数值
c++;
}
return a;
}
double numch(char *str)
{//转成非负整数
char wei[MAX]={0};//位数记录
char len=0;//下标最大值
double num[MAX]={0};
char x,k;//临时数据
char *t = str;//临时指针
while(len<MAX && *t)//循环,筛选整理
{
if(*t<='9' && *t>='0')//若是阿拉伯数字字符
{
x = *t - '0';//计算
t--;//阿拉伯数字只占一个字节
}
else
{
x = 0;
while(x<29 && (*t != *(_NUMBER+x*2) || *(t+1) != *(_NUMBER+x*2+1)))
x++;//检测比较中文字符
if(x==29)
break;//遇到非数字字符
if(x<21)
x = (x + 1) / 2;//0~9、十,代号10
else if(x==21)
x = 11;//廿,代号11
else if(x<26)
x = (x + 2) / 2;//百、千,代号12、13
else
x = x - 12;//万、兆、亿,代号14、15、16
}
if(x>=10)//遇到位代号记录位
{
*(wei+len)=x;//直接使用10~16作代号
len++;
k = 1;//k==1时关注如“二百五”==250的情况
}
else//遇到数字记录数字
{
if(!x)
k = 0;//遇到数字为0取消对“二百五”情况的关注
*(num+len) = *(num+len) * 10 + x;//每个位对应数字可以大于10
}
t += 2;//每个汉字占两个字节(阿拉伯数字已预先减1)
while(*t==' ')//其他处理,消除空格
t++;
if(*t ==',')//其他处理,遇到一个逗号
t++;
}
if(t == str)
return -1;//第一字符非数字字符
if(!len)//无单位类型返回
return num[0];
if(num[len])//不以0结尾
{
if(k)//关注“二百五”类型
if(!wei[len])//不以非“个”单位结尾
{
if(wei[len-1]>12)//“千”及以上单位
*(wei+len) = *(wei+len-1) - 1;//单位降1
else
if(*(wei+len-1) == 12)//单位“百”降一位是“十”,11是“廿”的代号
*(wei+len) = 10;
}
len ++;//凡不以0结尾,计算位数要加1
}
return _Num(num,wei,len);//进入递归环节
}
//下面验证一下:
#include "stdio.h"
void main()
{
printf("一二三四五六七八九十>>%.0f\n",numch("一二三四五六七八九十"));
printf("壹贰叁肆伍陆柒捌玖拾>>%.0f\n",numch("壹贰叁肆伍陆柒捌玖拾"));
printf("1,2 3,4 5,6 7,8 9,0 >>%.0f\n",numch("1,2 3,4 5,6 7,8 9,0 "));
printf("一贰三肆五陆七捌九拾>>%.0f\n",numch("一贰三肆五陆七捌九拾"));
printf("1 贰3,肆 5陆,7捌 9拾>>%.0f\n",numch("1 贰3,肆 5陆,7捌 9拾"));
printf("5十万3百>>%.0f\n",numch("5十万3百"));
printf("1 六>>%.0f\n",numch("1 六"));
printf("1,000>>%.0f\n",numch("1,000"));
printf("一>>%.0f\n",numch("一"));
printf("贰>>%.0f\n",numch("贰"));
printf("百>>%.0f\n",numch("百"));
printf("十万>>%.0f\n",numch("十万"));
printf("九亿五百万肆千>>%.0f\n",numch("九亿五百万肆千"));
printf("2兆廿一>>%.0f\n",numch("2兆廿一"));
printf("2佰伍>>%.0f\n",numch("2佰伍"));
printf("2佰0伍>>%.0f\n",numch("2佰0伍"));
while(getchar()!='\n');
}
[ 本帖最后由 LuoJun_LZ 于 2009-12-24 17:06 编辑 ] |
|