在C#中,我們經常需要表示整數。但是,c#的基本數據類型中,最大的long也只能表示-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807之間的數。貨幣類型也不是無限大。如果我們需要表示更大的數,就需要用到一定的算法來完成。
這次,我和大家一起討論一下c#的大數運算之加法。
這次,我們只考慮正數的整數加法。
我們的代碼要封裝到一個結構里面。這個結構的結構先擺出來。
public struct BigInt { public int[] num ; public int length ; }
我們的思路是讀取一個string表示的大數,然后通過算法來計算,返回一個string類型的結果。
為了便於計算,我們首先要把賦值過來的的string轉換為一個int數組。這個數組就是代碼里的num[]數組。
我們要把這個數的個位存到num[0]里,十位存到num[1]里,以此類推。於是我添加了一個構造函數。
public BigInt(string theint):this() { this.num = new int[200]; this.length = 0; this.length = theint.Length - 1; for (int i = 0; i <= theint.Length - 1; i++) { this.num[i] = Convert.ToInt32(theint[theint.Length - 1 - i].ToString()); } }
例如 調用BigInt(“123”) 時,num[0]=3,num[1]=2,num[2]=1 length=2 (為了方便,這里的length是指數組的坐標上限,不是數組元素的個數)
我們如果能直接把string賦給BigInt類型的變量該多方便啊,那么我們現在就來實現它。 怎么實現呢?其實把一種數據類型變量賦值給另一種時,都需要轉換,為什么有的可以直接賦值呢,是因為這里進行的是隱式轉換。所以我們就來編寫從string到BigInt的隱式轉換。代碼和構造函數類似。
public static implicit operator BigInt(string theint) { BigInt b = new BigInt(); b.num = new int[200]; b.length = 0; b.length = theint.Length - 1; for (int i = 0; i <= theint.Length - 1; i++) { b.num[i] = Convert.ToInt32(theint[theint.Length - 1 - i].ToString()); } return b; }
implicit說明轉換方式是隱式轉換。operator是各種轉換和操作符的標志。
當然,較小的數也可以直接從int轉過來。所以再寫一個int=>BigInt的隱式轉換。
public static implicit operator BigInt(long theint2) { string theint = theint2.ToString(); return theint; }
准備工作做好了,現在開始計算過程。
在這里,我們通過模擬學生列豎式的方法來計算。首先要從最低位也就是個位加起,滿10要向高位進1,也就是數組的下一個元素的值加一。我們直接重寫+操作符,代碼見下
public static BigInt operator +(BigInt b1, BigInt b2) { BigInt b3 = b1;//要返回的加法結果 BigInt b4 = b2; int big = b3.length > b4.length ? b3.length : b4.length;//獲取兩個加數的最高位數,從0到最高位數依次加法 for ( int i = 0; i <= big; i++) { b3.num[i] += b4.num[i];//加法計算 b3.num[i + 1] += b3.num[i] / 10;//進位 b3.num[i] %= 10; //進位后剩下的 } //確定更新后的位數 big=199; while (b3.num[big] == 0&&big!=0) { big--; } b3.length = big; return b3; }
public static BigInt operator +(BigInt b1, BigInt b2)這一句,BigInt是加法返回的結果的類型;operator +說明重寫的是加法,(BigInt b1, BigInt b2)是兩個加數。計算原理是豎式的加法計算。
代碼里我加入了注釋,應該可以看懂
最后,為了顯示BigInt類型的值,我們編寫一個由BigInt到string的隱式轉換。
public static implicit operator string(BigInt theint) { string b = ""; for (int i = theint.length; i >=0 ; i--) { b += theint.num[i].ToString(); } return b; }
由於存入數組時時從低位到高位的,所以我們輸出string時要反轉回來。
至此,大數加法編寫完成。下面是代碼清單。
public struct BigInt { public int[] num ; public int length ; #region 初始賦值 public BigInt(string s):this() { this = s; } public static implicit operator BigInt(string theint) { BigInt b = new BigInt(); b.num = new int[200]; b.length = 0; b.length = theint.Length - 1; for (int i = 0; i <= theint.Length - 1; i++) { b.num[i] = Convert.ToInt32(theint[theint.Length - 1 - i].ToString()); } return b; } public static implicit operator BigInt(long theint2) { string theint = theint2.ToString(); return theint; } #endregion public static implicit operator string(BigInt theint) { string b = ""; for (int i = theint.length; i >=0 ; i--) { b += theint.num[i].ToString(); } return b; }
public static BigInt operator +(BigInt b1, BigInt b2) { BigInt b3 = b1;//要返回的加法結果 BigInt b4 = b2; int big = b3.length > b4.length ? b3.length : b4.length;//獲取兩個加數的最高位數,從0到最高位數依次加法 for ( int i = 0; i <= big; i++) { b3.num[i] += b4.num[i];//加法計算 b3.num[i + 1] += b3.num[i] / 10;//進位 b3.num[i] %= 10; //進位后剩下的 } //確定更新后的位數 big=199; while (b3.num[big] == 0&&big!=0) { big--; } b3.length = big; return b3; }
}
另外注,此貼純屬技術研究,如需大數運算,.net有專門的類型,無需自己寫代碼。至於類型是什么,你們自己去找吧。O(∩_∩)O~