谈到atoi,相信大家非常熟悉了,就是把一个字符串转换成一个整数,具体实现的代码网上到处都能找到。这些字符串中的数字都是以阿拉伯数字的形式存在,即0、1、2、3、4、5、6、7、8、9,但是要是这些数字以汉字的形式出现,我们该如何转换呢?
假设这个汉字字符串一定是正确的,不会有错误输入,那么组成他的汉字字符就只包括零、一、二、三、四、五、六、七、八、九、十、百、千、万、亿。我们用UTF8编码的方式来处理这些汉字字符,因此每个字符长度都为2个字节。
一个汉字字符串到底有什么特点呢?以“九亿九千九百九十九万九千九百九十”为例,我们来做分析。首先,可以看出,这里面的亿、万、千、百、十,相当于一个基数radix,每个单位对应的值为100000000、10000、1000、100、10,而每个单位前面都会有一个小于10的数字,相当于一个值value,这两个字符串组成的值就是value * radix,因此对于这类数字,我们可以以两个字符为单位来进行处理,所以只能单独处理。然后,我们来总结一下下基数的规律:用sum表示总共的值,tmp表示当前累加的值,对于第i个基数radix[i],如果它小于第i - 1个基数radix[i - 1],就累加value[i] * radix[i]到tmp,否则就把(tmp + value[i]) * radix[i]加到sum,然后将tmp设为0。在这个例子中,基数的序列是“亿、千、百、十、万、千、百、十”,初始sum、tmp都为0,初始的基数为亿,下面介绍具体的步骤:
- “亿”:大于等于初始基数“亿”,sum加上(tmp + 9) * 100000000,为900000000,tmp为0
- ”千”:小于上一个基数“亿”,tmp加上9 * 1000,为9000
- “百”:小于上一个基数“千”,tmp加上9 * 100,为9900
- “十”:小于上一个基数“百”,tmp加上9 * 10,为9990
- “万”:大于等于上一个基数“千”,sum加上(tmp + 9) * 10000,为999990000,tmp为0
- “千”:小于上一个基数“万”,tmp加上9 * 1000, 为999999000
- “百”:小于上一个基数“千”,tmp加上9 * 100,为999999900
- “十”:小于上一个基数“百”,tmp加上9 * 10,为999999990
这样,我们就基本实现了一个中文版的atoi,但别高兴太早,因为还有很多特殊情况要处理。比如对于例子“九十九”,最后一个九无法处理;对于例子"十九",“十”被我们定义成为一个基数,但由于习惯,我们经常会把“一十九”说成“十九”,这样“十”前面就没有value了;对于例子“九十万”,“万”同样是一个基数,它前面也没有value。对于这些特例,我们可以发现,他们有同一个特点:如果我们以两个字符为单位取数字,它们处于两个字符中的第一个位置,然后它们的值都大于等于10。因此,对于这些数字,我们以一个字符为单位来进行处理,把它们当做radix,如果该radix小于前一个radix,就累加radix到tmp,否则就把tmp * radix到sum,然后将tmp设为0。这样我们就处理了这些特例情况。
最后,我们发现还有一个“零”没有处理过。对于“零”,我们也是以一个字符为单位来处理,因为它的值为0,所以我们直接忽略掉。
下面是我用java实现的代码,只能处理正确的输入哦。
import java.util.HashMap;
import java.util.Scanner;
public class ChineseAtoi {
private static HashMap<Character, Integer> map = new HashMap<Character, Integer>();
static {
map.put('零', 0);
map.put('一', 1);
map.put('两', 2);
map.put('二', 2);
map.put('三', 3);
map.put('四', 4);
map.put('五', 5);
map.put('六', 6);
map.put('七', 7);
map.put('八', 8);
map.put('九', 9);
map.put('十', 10);
map.put('百', 100);
map.put('千', 1000);
map.put('万', 10000);
map.put('亿', 100000000);
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String s = in.nextLine();
System.out.println(s);
ChineseAtoi c = new ChineseAtoi();
System.out.println(c.atoi(s));
in.close();
}
public long atoi(String s) {
long sum = 0, tmp = 0;
int preRadix = 100000000, curValue, curRadix;
for (int i = 0; i < s.length(); i++) {
curValue = map.get(s.charAt(i));
if (curValue > 0 && curValue <= 9) {
if (i + 1 < s.length()) {
curRadix = map.get(s.charAt(++i));
if (curRadix >= preRadix) {
sum += (tmp + curValue) * curRadix;
tmp = 0;
} else {
tmp += curValue * curRadix;
}
preRadix = curRadix;
} else {
tmp += curValue;
}
} else if (curValue >= 10) {
if (curValue >= preRadix) {
sum += tmp * curValue;
tmp = 0;
} else {
tmp += curValue;
}
preRadix = curValue;
}
}
sum += tmp;
return sum;
}
}
转载请注明出处: http://blog.csdn.net/sunset108/article/details/39159465