天天看點

中文數字版atoi【Java實作】

談到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,初始的基數為億,下面介紹具體的步驟:

  1. “億”:大于等于初始基數“億”,sum加上(tmp + 9) * 100000000,為900000000,tmp為0
  2. ”千”:小于上一個基數“億”,tmp加上9 * 1000,為9000
  3. “百”:小于上一個基數“千”,tmp加上9 * 100,為9900
  4. “十”:小于上一個基數“百”,tmp加上9 * 10,為9990
  5. “萬”:大于等于上一個基數“千”,sum加上(tmp + 9) * 10000,為999990000,tmp為0
  6. “千”:小于上一個基數“萬”,tmp加上9 * 1000, 為999999000
  7. “百”:小于上一個基數“千”,tmp加上9 * 100,為999999900
  8. “十”:小于上一個基數“百”,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