private static void AddSubTest(LongNumber a, LongNumber b) {// всякие тесты Console.WriteLine("***********************"); Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine("add-sub test"); Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("a = "); Console.ResetColor(); Console.WriteLine(a + " ( " + a.ToDecString() + " )"); Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("b = "); Console.ResetColor(); Console.WriteLine(b + " ( " + b.ToDecString() + " )"); var c = a + b; Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("a + b = "); Console.ResetColor(); Console.WriteLine(c + " ( " + c.ToDecString() + " )"); var d = a - b; Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("a - b = "); Console.ResetColor(); Console.WriteLine(d + " ( " + d.ToDecString() + " )"); a.ChandgeSing(); var k = a + b; Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("-a + b = "); Console.ResetColor(); Console.WriteLine(k + " ( " + k.ToDecString() + " )"); a.ChandgeSing(); Console.WriteLine("***********************"); }
private static void MulTest(LongNumber a, LongNumber b) {// тесты Console.WriteLine("***********************"); Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine("Multiply test"); Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("a = "); Console.ResetColor(); Console.WriteLine(a + " ( " + a.ToDecString() + " )"); Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("b = "); Console.ResetColor(); Console.WriteLine(b + " ( " + b.ToDecString() + " )"); var c = a * b; Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("a * b = "); Console.ResetColor(); Console.WriteLine(c + " ( " + c.ToDecString() + " )"); var d = c / b; Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("c / b = "); Console.ResetColor(); Console.WriteLine(d + " ( " + d.First.ToDecString() + " , " + d.Second.ToDecString() + " )"); var e = c / a; Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("c / a = "); Console.ResetColor(); Console.WriteLine(e + " ( " + e.First.ToDecString() + " , " + e.Second.ToDecString() + " )"); Console.WriteLine("***********************"); }
private static void DivTest(LongNumber a, LongNumber b) { //тесты Console.WriteLine("***********************"); Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine("Divide test"); Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("a = "); Console.ResetColor(); Console.WriteLine(a + " ( " + a.ToDecString() + " )"); Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("b = "); Console.ResetColor(); Console.WriteLine(b + " ( " + b.ToDecString() + " )"); var c = a / b; Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("a / b = "); Console.ResetColor(); Console.WriteLine(c + " ( " + c.First.ToDecString() + " , " + c.Second.ToDecString() + " )"); var d = (b * c.First + c.Second); Console.ForegroundColor = ConsoleColor.DarkYellow; Console.Write("c * a + b = "); Console.ResetColor(); Console.WriteLine(d + " ( " + d.ToDecString() + " )"); Console.WriteLine("***********************"); }
static void ComplexTest(LongNumber a, LongNumber b) {// общий тест, компелексный так сказать Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("######### Test set #" + (++_orderNumber) + " #########"); Console.ResetColor(); var st = DateTime.Now; var slt = DateTime.Now; AddSubTest(a, b); var lt = DateTime.Now - slt; Console.ForegroundColor = ConsoleColor.Magenta; Console.WriteLine("AddSubTest time " + lt.Seconds + " sec " + lt.Milliseconds + " msec"); Console.ResetColor(); slt = DateTime.Now; MulTest(a, b); lt = DateTime.Now - slt; Console.ForegroundColor = ConsoleColor.Magenta; Console.WriteLine("MulTest time " + lt.Seconds + " sec " + lt.Milliseconds + " msec"); Console.ResetColor(); slt = DateTime.Now; DivTest(a, b); lt = DateTime.Now - slt; Console.ForegroundColor = ConsoleColor.Magenta; Console.WriteLine("DivTest time " + lt.Seconds + " sec " + lt.Milliseconds + " msec"); Console.ResetColor(); var t = DateTime.Now - st; Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine("Total time " + t.Seconds + " sec " + t.Milliseconds + " msec"); Console.ResetColor(); Console.WriteLine(); }
// сложение public static LongNumber Add(LongNumber first, LongNumber second) { var sum = new LongNumber(first._discharges); var isCarry = false; for (int i = 0; i < second._discharges.Count; i++) { var add = sum._discharges[i] + second._discharges[i] + (isCarry ? 1 : 0); isCarry = (add >> 8) > 0; sum._discharges[i] = (byte)add; } var carryIndex = second._discharges.Count; while (isCarry) { if (sum._discharges.Count > carryIndex) { sum._discharges[carryIndex] += 1; if (sum._discharges[carryIndex] != 0) isCarry = false; carryIndex++; } else { sum._discharges.Add(1); isCarry = false; } } return sum; }
// специальное сложение для умножения. чтоб быстрее private static void multuADD(LongNumber output, LongNumber longNumber, int index) { var isCarry = false; for (int i = 0; i < longNumber._discharges.Count; i++) { if (output._discharges.Count == i + index) output._discharges.Add(0); var add = output._discharges[i+index] + longNumber._discharges[i] + (isCarry ? 1 : 0); isCarry = (add >> 8) > 0; output._discharges[i+index] = (byte)add; } var carryIndex = longNumber._discharges.Count+index; while (isCarry) { if (output._discharges.Count > carryIndex) { output._discharges[carryIndex] += 1; if (output._discharges[carryIndex] != 0) isCarry = false; carryIndex++; } else { output._discharges.Add(1); isCarry = false; } } }
static void Main(string[] args) { var a = new LongNumber(new List <byte> { 255, 1 }); var b = new LongNumber(new List <byte> { 1, 255 }); ComplexTest(a, b); a = new LongNumber(new List <byte> { 255, 255, 255, 255 }); b = new LongNumber(new List <byte> { 1, 0, 0, 0, 1 }); ComplexTest(a, b); a = LongNumber.FromDecString("+1000000000000000000000000000"); b = LongNumber.FromDecString("+1000000000000000000000000000"); ComplexTest(a, b); }
// сранение 1 - первое больше, -1 первое меньше, 0 - равны public static int AbsCompare(LongNumber first, LongNumber second) { if (first._discharges.Count < second._discharges.Count) return -1; if (first._discharges.Count > second._discharges.Count) return 1; for (int i = first._discharges.Count - 1; i >= 0; i--) { if (first._discharges[i] < second._discharges[i]) return -1; if (first._discharges[i] > second._discharges[i]) return 1; } return 0; }
// перегруз оператора. учтено, что иногда сложение - это вычитание (например -5+3 - это 3 - 5) public static LongNumber operator -(LongNumber first, LongNumber second) { if (first.Equals(second)) second = new LongNumber(second._discharges) {_isNegative = !first._isNegative}; else second._isNegative = ! second._isNegative; var output = first + second; second._isNegative = !second._isNegative; return output; }
// из десятичной строки public static LongNumber FromDecString(string s) { var output = new LongNumber(new List<byte> { 0 }); for (int i = 1; i < s.Length; i++) { output *= 10; output += new LongNumber(new List<byte> { (byte)(s[i] - '0') }); } output._isNegative = s[0] == '-'; return output; }
public static LongNumber Factorial(int inputValue) { LongNumber[] fact = new LongNumber[inputValue + 1]; fact[0] = new LongNumber("0"); fact[1] = new LongNumber("1"); fact[2] = new LongNumber("2"); LongNumber j = new LongNumber("3"); for (int i = 3; i <= inputValue - 2; i++) { fact[i] = fact[i - 1] * j; } return(fact[inputValue - 2]); }
// умножение длинного на байт public static LongNumber operator *(LongNumber ln, byte b) { var output = new LongNumber(ln._discharges); byte carry = 0; for (int i = 0; i < output._discharges.Count; i++) { int intermediate = output._discharges[i]*b; var addCarry = ((intermediate & 255) + carry) >> 8; output._discharges[i] = (byte) ((intermediate & 255) + carry); carry = (byte) ((intermediate >> 8)+addCarry); } if (carry>0) output._discharges.Add(carry); return output; }
// в десятичную строку public string ToDecString() { var sb = new StringBuilder(); sb.Append(Sign()); var forOut = new LongNumber(_discharges); var ten = new LongNumber(new byte[] { 10 }); while (forOut._discharges.Count>1||forOut._discharges[0] > 9) { var div = forOut / ten; forOut = div.First; sb.Insert(1, (char)('0' + div.Second._discharges[0])); } sb.Insert(1, (char)('0' + forOut._discharges[0])); return sb.ToString(); }
public static void Main() { LongNumber a = new LongNumber(new List <int>() { 0, 0, 1 }, true); LongNumber c = new LongNumber(new List <int>() { 0, 2 }, true); // int b = 200; // LongNumber d = new LongNumber(new List<int>() { 0, 1 }, true); // d += b; LongNumber q = new LongNumber("-123"); Console.WriteLine(Factorial(10)); }
// деление (частное, остаток) public static Cont <LongNumber,LongNumber> operator /(LongNumber first, LongNumber second) { var output = new LongNumber(); var residue = new LongNumber(first._discharges,first._isNegative); if (AbsCompare(first, second) == -1) { output._discharges.Add(0); return new Cont<LongNumber, LongNumber>(output, residue); } var discharge = residue._discharges.Count - second._discharges.Count; for (int i = 0; i < discharge; i++) second._discharges.Insert(0,0); for (int i = 0; i < discharge; i++) { if (AbsCompare(residue, second) == -1) output._discharges.Insert(0, 0); else { var cont = getDivider(residue, second); output._discharges.Insert(0, cont.First); residue = cont.Second; } second._discharges.RemoveAt(0); } if (AbsCompare(residue, second) == -1) output._discharges.Insert(0, 0); else { var cont = getDivider(residue, second); output._discharges.Insert(0, cont.First); residue = cont.Second; } var lastIndex = output._discharges.Count; while (lastIndex != 0 && output._discharges[--lastIndex] == 0) ; output._discharges.RemoveRange(lastIndex + 1, output._discharges.Count - lastIndex - 1); output._isNegative = first._isNegative != second._isNegative; return new Cont<LongNumber, LongNumber>(output,residue); }
// широкую на широкую! умножаем public static LongNumber operator *(LongNumber first, LongNumber second) { var output = new LongNumber(); if (AbsCompare(first, second) == -1) { var temp = second; second = first; first = temp; } for (int i = 0; i < second._discharges.Count; i++) multuADD (output, first*second._discharges[i], i); var lastIndex = output._discharges.Count; while (lastIndex != 0 && output._discharges[--lastIndex] == 0) ; output._discharges.RemoveRange(lastIndex + 1, output._discharges.Count - lastIndex - 1); output._isNegative = first._isNegative != second._isNegative; return output; }
// подбор очередного байта частного методом дихотомии. (гуглить "окулов длинная арифметика") private static Cont<Byte,LongNumber> getDivider(LongNumber residue, LongNumber second) { var down = 0; var up = 256; while (down + 1 < up) { var newValue = second*(byte) ((down + up)/2); if (AbsCompare(residue, newValue) == -1) { up = (down + up) / 2; } else { down = (down + up) / 2; } } var residueOut = Subtract(residue, second * (byte)down); residueOut._isNegative = residue._isNegative; return new Cont<Byte,LongNumber>((byte)down, residueOut); }
// вычитание public static LongNumber Subtract(LongNumber first, LongNumber second) { var sum = new LongNumber(first._discharges); var isCarry = false; for (int i = 0; i < second._discharges.Count; i++) { var isCarryNext = sum._discharges[i] < second._discharges[i] ; sum._discharges[i] -= (byte)(second._discharges[i] + (isCarry ? 1 : 0)); isCarry = isCarryNext; } var carryIndex = second._discharges.Count; while (isCarry) { if (sum._discharges[carryIndex] != 0) isCarry = false; sum._discharges[carryIndex] -= 1; carryIndex++; } var lastIndex = sum._discharges.Count; while (lastIndex !=0 && sum._discharges[--lastIndex] == 0); sum._discharges.RemoveRange(lastIndex + 1, sum._discharges.Count-lastIndex-1); return sum; }
public LongNumber(LongNumber ln) { _discharges = ln._discharges; }