一、題目:打印1到最大的n位數
題目:輸入數字n,按順序打印出從1最大的n位十進制數。比如輸入3,則打印出1、2、3一直到最大的3位數即999。
二、不同的解法
2.1 不假思索的解法
最容易想到的辦法是先求出最大的n位數,然后用一個循環從1開始逐個打印:
static void Print1ToMaxOfNDigitsSimple(int n) { int number = 1; int i = 0; while (i < n) { number = number * 10; i++; } for (i = 1; i < number; i++) { Console.Write("{0}\t", i); } }
初看之下好像沒有問題,但是其並沒有考慮大數問題,有可能即使用整型(int)或長整型(long)都會溢出。
2.2 字符串模擬運算的解法
解決這個問題需要表達一個大數。最常用也是最容易的方法是用字符串或者數組表達大數。該算法的步驟如下:
Step1.把字符串中的每一個數字都初始化為'0';
Step2.每一次為字符串表示的數字加1,再打印出來;
static void Print1ToMaxOfNDigits(int n) { if (n <= 0) { return; } // memset(number,'0',n); char[] number = new char[n + 1]; for (int i = 0; i < n; i++) { number[i] = '0'; } number[n] = '\0'; // Increment實現在表示數字的字符串number上增加1 while (!Increment(number)) { // PrintNumber負責打印出number PrintNumber(number); } number = null; } static bool Increment(char[] number) { bool isOverflow = false; int takeOver = 0; int length = number.Length - 1; for (int i = length - 1; i >= 0; i--) { int sum = number[i] - '0' + takeOver; if (i == length - 1) { sum++; } if (sum >= 10) { if (i == 0) { // 標識已經溢出了 isOverflow = true; } else { sum -= 10; takeOver = 1; number[i] = (char)('0' + sum); } } else { number[i] = (char)('0' + sum); break; } } return isOverflow; } static void PrintNumber(char[] number) { bool isBeginning0 = true; for (int i = 0; i < number.Length; i++) { if (isBeginning0 && number[i] != '0') { isBeginning0 = false; } if (!isBeginning0) { Console.Write("{0}", number[i]); } } Console.Write("\t"); }
這里要注意的是:當數字不夠n位的時候,我們在數字的前面補0,打印的時候這些補位的0不應該打印出來。
三、單元測試
3.1 封裝測試入口
static void PrintTest(int n) { Console.WriteLine("Test for {0} begins:", n); Print1ToMaxOfNDigits(n); Console.WriteLine("Test for {0} ends.", n); }
3.2 測試用例
static void Main(string[] args) { PrintTest(1); PrintTest(2); PrintTest(3); PrintTest(0); PrintTest(-1); Console.ReadKey(); }