LargeNumbers(NumSign sign, IEnumerable <int> digits, int decimalPlaces) { Sign = sign; Digits = new ReadOnlyCollection <int>(digits.ToList()); DecimalPlaces = decimalPlaces; }
public static LargeNumbers Sub(LargeNumbers first, LargeNumbers second) { if (first.Sign == NumSign.Negative && second.Sign == NumSign.Positive) { LargeNumbers positiveFirst = new LargeNumbers(NumSign.Positive, first.Digits, first.DecimalPlaces); LargeNumbers sum = Add(positiveFirst, second); return(new LargeNumbers(NumSign.Negative, sum.Digits, sum.DecimalPlaces)); } else if (first.Sign == NumSign.Positive && second.Sign == NumSign.Negative) { LargeNumbers positiveSecond = new LargeNumbers(NumSign.Positive, second.Digits, second.DecimalPlaces); return(Add(first, positiveSecond)); } else { List <int> digits1 = first.Digits.ToList(); List <int> digits2 = second.Digits.ToList(); List <int> resultDigits = new List <int>(); NumSign resultSign = new NumSign(); if ((digits1.Count - first.DecimalPlaces) < (digits2.Count - second.DecimalPlaces)) { if (first.Sign == NumSign.Positive && second.Sign == NumSign.Positive) { LargeNumbers sum = Sub(second, first); return(new LargeNumbers(NumSign.Negative, sum.Digits, sum.DecimalPlaces)); } else if (first.Sign == NumSign.Negative && second.Sign == NumSign.Negative) { LargeNumbers sum = Sub(second, first); return(new LargeNumbers(NumSign.Positive, sum.Digits, sum.DecimalPlaces)); } } int maxDigitsBeforeDecimalPoint = Math.Max( (digits1.Count - first.DecimalPlaces), (digits2.Count - second.DecimalPlaces)); digits1.InsertRange(0, Enumerable.Repeat(0, maxDigitsBeforeDecimalPoint - (digits1.Count - first.DecimalPlaces))); digits2.InsertRange(0, Enumerable.Repeat(0, maxDigitsBeforeDecimalPoint - (digits2.Count - second.DecimalPlaces))); int maxDigitsAfterDecimalPoint = Math.Max( first.DecimalPlaces, second.DecimalPlaces ); digits1.AddRange(Enumerable.Repeat(0, maxDigitsAfterDecimalPoint - first.DecimalPlaces)); digits2.AddRange(Enumerable.Repeat(0, maxDigitsAfterDecimalPoint - second.DecimalPlaces)); int carry = 0; if (digits1[0] < digits2[0]) { if (first.Sign == NumSign.Positive && second.Sign == NumSign.Positive) { LargeNumbers sum = Sub(second, first); return(new LargeNumbers(NumSign.Negative, sum.Digits, sum.DecimalPlaces)); } else if (first.Sign == NumSign.Negative && second.Sign == NumSign.Negative) { LargeNumbers sum = Sub(second, first); return(new LargeNumbers(NumSign.Positive, sum.Digits, sum.DecimalPlaces)); } } else if (digits1[0] == digits2[0]) { int i = -1; do { ++i; if (i == digits1.Count - 1 && i == digits2.Count - 1 && digits1[i] == digits2[i]) { break; } else if (digits1[i] < digits2[i]) { if (first.Sign == NumSign.Positive && second.Sign == NumSign.Positive) { LargeNumbers sum = Sub(second, first); return(new LargeNumbers(NumSign.Negative, sum.Digits, sum.DecimalPlaces)); } else if (first.Sign == NumSign.Negative && second.Sign == NumSign.Negative) { LargeNumbers sum = Sub(second, first); return(new LargeNumbers(NumSign.Positive, sum.Digits, sum.DecimalPlaces)); } } } while (digits1[i] == digits2[i] && i != digits2.Count); } for (int i = digits1.Count - 1; i >= 0; i--) { if (digits1[i] - digits2[i] - carry < 0) { resultDigits.Insert(0, (10 - digits2[i] + digits1[i] - carry)); carry = 1; } else { resultDigits.Insert(0, ((digits1[i] - carry) - digits2[i])); carry = 0; } } if (carry == 0) { resultSign = first.Sign; } if (carry == 1) { resultSign = second.Sign; } return(new LargeNumbers(resultSign, resultDigits, maxDigitsAfterDecimalPoint)); } }