长数据类
public class LongNumber{public enum NumberFlag{/// <summary>/// 負數/// </summary>
Negative,/// <summary>/// 正數/// </summary>
Positive}public NumberFlag Flag { get; set; }public string Number { get; set; }public LongNumber(){this.Flag = NumberFlag.Positive;this.Number = "0";}public LongNumber(string number){if (!LongNumber.CheckNumber(number))throw new InvalidCastException("Input not is a number.");this.Flag = NumberFlag.Positive;this.Number = number;}public LongNumber(NumberFlag flag, string number){if (!LongNumber.CheckNumber(number))throw new InvalidCastException("Input not is a number.");this.Flag = flag;this.Number = number;}public override string ToString(){if (LongNumber.EqualsZero(this))return "0";else{return string.Format("{0}{1}", this.Flag == NumberFlag.Positive ? string.Empty : "-", this.Number.TrimStart('0'));}}/// <summary>/// 檢測給定字符串是否是一個有效的數字/// </summary>/// <param name="a"></param>/// <returns></returns>public static bool CheckNumber(string a){if (string.IsNullOrWhiteSpace(a))return false;var content = a;foreach (var item in content){if (!"0123456789.".Contains(item)){return false;}}return true;}/// <summary>/// 檢測給定的數字是否等于零/// </summary>/// <param name="a"></param>/// <returns></returns>public static bool EqualsZero(LongNumber a){var pos = a.Number.LastIndexOf('.');var left = a.Number;var right = string.Empty;if (pos >= 0){left = a.Number.Substring(0, pos);right = a.Number.Substring(pos + 1);}if (left.Any(c => c != '0') || right.Any(c => c != '0'))return false;return true;}public static LongNumber Add(LongNumber a, LongNumber b){if (a.Flag == b.Flag)return new LongNumber(a.Flag, AddWithoutFlag(a, b).Number);else if (a.Flag == NumberFlag.Negative)return LongNumber.MinusWithoutFlag(b, new LongNumber(NumberFlag.Positive, a.Number));elsereturn LongNumber.MinusWithoutFlag(a, new LongNumber(NumberFlag.Positive, b.Number));}/// <summary>/// 計算a加b的結果/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <returns></returns>private static LongNumber AddWithoutFlag(LongNumber a, LongNumber b){//格式化數據var inputA = a.Number;var inputB = b.Number;FormatNumber(ref inputA, ref inputB);a.Number = inputA;b.Number = inputB;//定義進位值var carry = 0;var sbResult = new StringBuilder();for (var i = a.Number.Length - 1; i >= 0; i--){var tempA = a.Number[i];var tempB = b.Number[i];if (tempA == '.'){sbResult.Insert(0, tempA);continue;}var tempResult = int.Parse(tempA.ToString()) + int.Parse(tempB.ToString()) + carry;if (tempResult > 9){carry = 1;tempResult -= 10;}else{carry = 0;}sbResult.Insert(0, tempResult.ToString());}if (carry > 0)sbResult.Insert(0, carry);return new LongNumber(sbResult.ToString());}public static LongNumber Minus(LongNumber a, LongNumber b){if (a.Flag == b.Flag){var c = LongNumber.MinusWithoutFlag(new LongNumber(a.Number), new LongNumber(b.Number));if (a.Flag == NumberFlag.Negative)c = new LongNumber(c.Flag == NumberFlag.Positive ? NumberFlag.Negative : NumberFlag.Positive, c.Number);return c;}else{var c = LongNumber.AddWithoutFlag(new LongNumber(a.Number), new LongNumber(b.Number));if (a.Flag == NumberFlag.Negative)c = new LongNumber(c.Flag == NumberFlag.Positive ? NumberFlag.Negative : NumberFlag.Positive, c.Number);return c;}}/// <summary>/// 計算a減b的結果/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <returns></returns>private static LongNumber MinusWithoutFlag(LongNumber a, LongNumber b){var resultFlag = NumberFlag.Positive;if (Compare(a, b) < 0){resultFlag = NumberFlag.Negative;var tempC = a.Number;a.Number = b.Number;b.Number = tempC;}//格式化數據var inputA = a.Number;var inputB = b.Number;FormatNumber(ref inputA, ref inputB);a.Number = inputA;b.Number = inputB;//定義借位var borrow = 0;var sbResult = new StringBuilder();for (var i = a.Number.Length - 1; i >= 0; i--){var tempA = a.Number[i];var tempB = b.Number[i];if (tempA == '.'){sbResult.Insert(0, tempA);continue;}var tempResult = int.Parse(tempA.ToString()) - int.Parse(tempB.ToString()) - borrow;if (tempResult < 0){borrow = 1;tempResult += 10;}else{borrow = 0;}sbResult.Insert(0, tempResult.ToString());}return new LongNumber(resultFlag, sbResult.ToString());}/// <summary>/// 計算a乘以b的結果/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <returns></returns>public static LongNumber Multiply(LongNumber a, LongNumber b){//獲取小數位數var aDecimalDigits = getDecimalDigits(a.Number);var bDecimalDigits = getDecimalDigits(b.Number);a.Number = a.Number.Replace(".", string.Empty);b.Number = b.Number.Replace(".", string.Empty);//用b從右到左的每一位去乘avar totalResult = new LongNumber("0");for (var i = b.Number.Length - 1; i >= 0; i--){var tempResult = new LongNumber("0");for (var j = 0; j < int.Parse(b.Number[i].ToString()); j++){tempResult = Add(tempResult, a);}var sb = new StringBuilder();for (var j = 0; j < b.Number.Length - 1 - i; j++){sb.Append('0');}sb.Insert(0, tempResult.Number);totalResult = Add(totalResult, new LongNumber(sb.ToString()));}var sbResult = new StringBuilder(totalResult.Number);if (aDecimalDigits + bDecimalDigits > 0)sbResult.Insert(sbResult.Length - aDecimalDigits - bDecimalDigits, '.');var resultFlag = LongNumber.NumberFlag.Positive;if (a.Flag != b.Flag)resultFlag = NumberFlag.Negative;return new LongNumber(resultFlag, sbResult.ToString());}/// <summary>/// 計算a除以b的結果,保留maxDecimalDigits位小數/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <param name="maxDecimalDigits"></param>/// <returns></returns>public static LongNumber Devide(LongNumber a, LongNumber b, int maxDecimalDigits = 2){var result = new StringBuilder();var numberA = new StringBuilder();//按照手動除法的規律去從高到低按位除for (var i = 0; i < a.Number.Length; i++){if (a.Number[i] == '.'){if (result.Length == 0)result.Append(0);result.Append('.');continue;}//取被除數下一位
numberA.Append(a.Number[i].ToString());var tempA = new LongNumber(numberA.ToString());//如果當前取到的被除數位數與上次結果組合后大于等于除數,則可以除if (Compare(tempA, b) >= 0){var tempResult = 0;//循環減一次除數,以累積計算當前位的最大商while (Compare(tempA, b) >= 0){tempResult++;tempA = Minus(tempA, b);}result.Append(tempResult);numberA.Clear();numberA.Append(tempA);}//如果當前取到的被除數位數與上次結果組合后小于除數,則商當前位填0else{result.Append(0);}}var resultFlag = LongNumber.NumberFlag.Positive;if (a.Flag != b.Flag)resultFlag = NumberFlag.Negative;return new LongNumber(resultFlag, result.ToString());}/// <summary>/// 計算a的b次方/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <returns></returns>public static LongNumber Power(LongNumber a, LongNumber b){var result = new LongNumber("1");var counter = new LongNumber("0");while (Compare(counter, b) < 0){result = Multiply(result, new LongNumber(a.Flag, a.Number));counter = Add(counter, new LongNumber("1"));}return result;}/// <summary>/// 比較兩個長整數的大小/// </summary>/// <param name="a"></param>/// <param name="b"></param>/// <returns></returns>public static int Compare(LongNumber a, LongNumber b){if (LongNumber.EqualsZero(a) && LongNumber.EqualsZero(b))return 0;//格式化數據var inputA = a.Number;var inputB = b.Number;FormatNumber(ref inputA, ref inputB);a.Number = inputA;b.Number = inputB;var flagA = a.Flag;var flagB = b.Flag;if (!LongNumber.EqualsZero(a))flagA = a.Flag;if (!LongNumber.EqualsZero(b))flagB = b.Flag;if (flagA > flagB)return 1;else if (flagA < flagB)return -1;else{for (var i = 0; i < a.Number.Length; i++){var itemA = int.Parse(a.Number[i].ToString());var itemB = int.Parse(b.Number[i].ToString());if (itemA == itemB)continue;if (itemA > itemB)return 1;elsereturn -1;}return 0;}}/// <summary>/// 進制轉換/// </summary>/// <param name="num">要轉換的數字</param>/// <param name="toBase">要轉換的進制基數</param>/// <returns>轉換進制后每一位的數據</returns>public static List<LongNumber> BaseCast(LongNumber num, LongNumber toBase){if (LongNumber.Compare(toBase, new LongNumber("0")) < 0)throw new InvalidCastException("toBase must be a positive number");var result = new List<LongNumber>();var temp = new LongNumber(num.Flag, num.Number);while (true){var a = LongNumber.Devide(temp, toBase, 0);var b = LongNumber.Multiply(a, toBase);var c = LongNumber.Minus(temp, b);if (LongNumber.Compare(c, new LongNumber("0")) < 0)c = LongNumber.Add(c, toBase);result.Add(c);if (LongNumber.EqualsZero(a))break;temp = a;}result.Reverse();return result;}/// <summary>/// 往小數點后面的小數位末尾補0,在小數左邊補零,以使兩數左右對齊/// </summary>/// <param name="a"></param>/// <param name="b"></param>private static void FormatNumber(ref string a, ref string b){//獲取小數位數var aDecimalDigits = getDecimalDigits(a);var bDecimalDigits = getDecimalDigits(b);//補齊小數位數,使其右對齊var sb = new StringBuilder();for (var i = 0; i < Math.Abs(aDecimalDigits - bDecimalDigits); i++){sb.Append('0');}if (aDecimalDigits > bDecimalDigits){sb.Insert(0, b);b = sb.ToString();}else if (bDecimalDigits > aDecimalDigits){sb.Insert(0, a);a = sb.ToString();}//補齊左邊位數,使其可以左對齊
sb.Clear();for (var i = 0; i < Math.Abs(a.Length - b.Length); i++){sb.Append('0');}if (a.Length > b.Length){sb.Append(b);b = sb.ToString();}else if (b.Length > a.Length){sb.Append(a);a = sb.ToString();}}/// <summary>/// 獲取小數位數/// </summary>/// <param name="a"></param>/// <returns></returns>private static int getDecimalDigits(string a){return a.IndexOf('.') >= 0 ? a.Length - a.IndexOf('.') - 1 : 0;}}
?
轉載于:https://www.cnblogs.com/nanfei/p/10268391.html
總結
- 上一篇: bzoj2597: [Wc2007]剪刀
- 下一篇: 浅谈严格模式和混杂模式