开始主要是mush玩游戏用,发现没有满意的算法,就自己写了一个。用数位和权的方法,兼容习惯性说法 -- 通过扩充digit_c、digit_rate,可以支持大写等 local digit_c={ ['零'] = 0, ['一'] = 1, ['二'] = 2, ['三'] = 3, ['四'] = 4, ['五'] = 5, ['六'] = 6, ['七'] = 7, ['八'] = 8, ['九'] = 9 } local digit_rate={ ['十']=1, ['百']=2, ['千']=3, ['万']=4, ['亿']=8 } function ctoi(a_num_c) local t_rate ={} local t_num = {} local num_c = a_num_c for i=1,string.len(num_c), 2 do local c = string.sub(num_c,i,i+1) local num = digit_c[c] local rate = digit_rate[c] if (num ~= nil) then table.insert(t_num, num) table.insert(t_rate, 0) elseif (rate ~= nil) then table.insert(t_rate, rate) table.insert(t_num, 0) else --TODO,跳过不支持的 end end -- dump rate=num --scan rate, special for 十, ie, 十万,零十八之类 if (t_rate[1] ~= 0) then table.insert(t_rate, 1, 0) table.insert(t_num, 1, 1) end -- 不需要递归,直接将前面一个数字设置为1 for i=1, table.getn(t_rate) do if (t_rate[i] ~= 0 and t_rate[i-1] ~= 0 and math.fmod(t_rate[i],4) ~= 0) then t_num[i-1] = 1 elseif (t_rate[i] == 1 and t_rate[i-1] ==0 and t_num[i-1] == 0) then -- for 零十八这种情况 t_num[i-1] = 1 end end -- scan rate, sepcial for 4,8 local idx_4 = 0 local idx_8 = 0 for i=1, table.getn(t_rate) do if (t_rate[i] == 4) then idx_4 = i for j=idx_8+1, idx_4-1 do if (t_rate[j] ~= nil and t_rate[j] ~= 0) then t_rate[j] = t_rate[j] + 4 end -- if end -- for j elseif (t_rate[i] == 8) then -- rate == 4 idx_8 = i for j=0, idx_8-1 do if (t_rate[j] ~= nil and t_rate[j] ~= 0) then t_rate[j] = t_rate[j] + 8 end -- if end -- for j end -- rate == 4 end -- for scan t_rate -- 如果最后一位是数字,两种情况,一是类似一万八这种,一是一万零八,或者十八这类 -- 区别是前面情况,前面的rate非0,后面则为0或者1 -- 为最后一位数字增加rate if (t_num[table.getn(t_num)] ~= 0) then local before = t_rate[table.getn(t_num) - 1] if (before == nil or before == 0) then table.insert(t_rate, 0) table.insert(t_num, 0) else table.insert(t_rate, before - 1) table.insert(t_num, 0) end end --calc local result = 0 for i=1, table.getn(t_rate)-1 do result = result + t_num[i] * math.pow(10, t_rate[i+1]) end return result; end 想了想,弄了个C的,放着备用 #include <stdio.h> #include <stdlib.h> #include <string.h> //#include <math.h> // pow static const unsigned short CHINESE_MAX_RATE = 20; //max rate, in fact, it's max long // For gcc, pow in math.h does not work sometimes, so ... static inline long int mypow(int a, int n) { int i; int ret = 1; for (i=0; i<n; i++) { ret *= a; } return ret; } // convert chinese num, can add 壹...玖 to support upper chinese num // -1 for error static int get_digit_c(const char* digit_c) { if (0==strncmp(digit_c, "零", 2)) return 0; else if (0==strncmp(digit_c, "一", 2)) return 1; else if (0==strncmp(digit_c, "二", 2)) return 2; else if (0==strncmp(digit_c, "三", 2)) return 3; else if (0==strncmp(digit_c, "四", 2)) return 4; else if (0==strncmp(digit_c, "五", 2)) return 5; else if (0==strncmp(digit_c, "六", 2)) return 6; else if (0==strncmp(digit_c, "七", 2)) return 7; else if (0==strncmp(digit_c, "八", 2)) return 8; else if (0==strncmp(digit_c, "九", 2)) return 9; return -1; } // convert chinese rate, can add 拾...萬 to support upper chinese rate // -1 for error static int get_digit_rate(const char* digit_rate) { if (0==strncmp(digit_rate, "十", 2)) return 1; else if (0==strncmp(digit_rate, "百", 2)) return 2; else if (0==strncmp(digit_rate, "千", 2)) return 3; else if (0==strncmp(digit_rate, "万", 2)) return 4; else if (0==strncmp(digit_rate, "亿", 2)) return 8; return -1; } // convert a chinese number to number long int myctoi(const char* a_num_c) { int i; int idx_4 = 0; int idx_8 = 0; long int result = 0; int t_rate[CHINESE_MAX_RATE]; int t_num[CHINESE_MAX_RATE]; int cnt = 0; for (i=0; i<CHINESE_MAX_RATE; i++) { t_rate[i] = -1; t_num[i] = -1; } //printf("Convert %s .../n", a_num_c); for (i=0; i<strlen(a_num_c); i+=2) { char c[4]; int num, rate; strncpy(c, a_num_c + i, 2); c[2]='/0'; //printf("%d -> %s/n", i, c); num = get_digit_c(c); rate = get_digit_rate(c); if (num != -1) { t_num[cnt] = num; t_rate[cnt] = 0; } else if (rate != -1) { t_num[cnt] = 0; t_rate[cnt] = rate; } else { //TODO: skip not support } cnt ++; } // scan rate, special for 十, ie, 十万,零十八之类 if (t_rate[0] != 0) { for (i=cnt; i>0; i--) { t_num[i] = t_num[i-1]; t_rate[i] = t_rate[i-1]; } t_num[0] = 1; t_rate[0] = 0; cnt++; } for (i=1; i<cnt; i++) { if (t_rate[i] != 0 && t_rate[i-1] != 0 && t_rate[i] % 4 != 0) { t_num[i-1] = 1; } else if (t_rate[i] == 1 && t_rate[i-1] ==0 && t_num[i-1] == 0) // for 零十八这种情况 { t_num[i-1] = 1; } } // scan rate, sepcial for 4,8 for (i=0; i<cnt; i++) { if (t_rate[i] == 4) { int j; idx_4 = i; for ( j=idx_8+1; j<=idx_4-1; j++) { if (t_rate[j] != -1 && t_rate[j] != 0) { t_rate[j] = t_rate[j] + 4; } } } else if (t_rate[i] == 8) // rate == 4 { int j; idx_8 = i; for (j=0; j<=idx_8-1; j++) { if (t_rate[j] != -1 && t_rate[j] != 0) { t_rate[j] = t_rate[j] + 8; } } } } // 如果最后一位是数字,两种情况,一是类似一万八这种,一是一万零八,或者十八这类 // 区别是前面情况,前面的rate非0,后面则为0或者1 // 为最后一位数字增加rate if (t_num[cnt-1] != 0) { int before = t_rate[cnt- 1 - 1]; if (before == -1 || before == 0) { t_rate[cnt] = 0; t_num[cnt] = 0; } else { t_rate[cnt] = before - 1; t_num[cnt] = 0; } cnt++; } // calc result = 0; for (i=0; i<cnt-1; i++) { result = result + t_num[i] * mypow(10, t_rate[i+1]); } return result; } int main(int argc, char** argv) { printf("%ld/n", myctoi("十万零一百三十二")); printf("%ld/n", myctoi("十八")); printf("%ld/n", myctoi("十八万零十八")); printf("%ld/n", myctoi("十八万零一百一十八")); printf("%ld/n", myctoi("一十八万零一百十八")); return 0; }