public static LongNumber Task6(int k) // Задача номер СЕМЬ! { // Переменная для ответа. LongNumber a = new LongNumber("2"); // Переменная для текущего результата. LongNumber q = new LongNumber("1"); // Переменная для проверки точности. LongNumber w = new LongNumber("1"); // "Длинная" единица для удобства. LongNumber x = new LongNumber("1"); // Итерационная переменная. int i = 2; // Пременная для знака. int p = -1; // Пока не дошли до указанной точности и не вышли за границы int32. while ((a.GetExp() <= k * 2) && (i < int.MaxValue)) { // Считаем. q.SetMaxExp(k); q.EqualTo(x / i); q.EqualTo(q * p); a.EqualTo(a + q); // Проверяем точность. w.EqualTo(a - w); int j = a.num.Count; if (a.GetExp() > k) { while (j >= k) { if (w.num[j - 1] != 0) { break; } j--; } if (j <= k) { break; } } // Сохраняем текущий результат. w.EqualTo(a); // Двигаем итерацию. i += 2; // Меняем знак. p *= -1; } a.EqualTo(a * 2); return(a); }
public static LongNumber Task10(LongNumber k, LongNumber n) // Задача номер ДЕСЯТЬ! { // Переменная для ответа. LongNumber a = new LongNumber(); // Длинная единица, для удобства. LongNumber b = new LongNumber("1"); // Считаем сумму геометрической прогрессии. a.EqualTo(k); LongNumber.UpToPow(a, n); a.EqualTo(b - a); b.EqualTo(b - k); a.EqualTo(a / b); a.RemoveZeros(); return(a); }
public static void Task16() // Задача номер ШЕСТНАДЦАТЬ! { // Массив со степенями. int[] p = new int[] { 2, 3, 5, 7, 13, 17, 19, 31, 61, 89 }; LongNumber q = new LongNumber("2"); LongNumber b = new LongNumber("1"); // Переменная для ответа. LongNumber a = new LongNumber(); // Идём по степеням в массиве и считаем числа Мерсенна. for (int i = 0; i < 10; i++) { a.EqualTo(q); a.EqualTo(LongNumber.UpToPow(a, p[i])); a.EqualTo(a - b); a.WriteOut(); } }
public static LongNumber operator *(LongNumber x, int y) // Перегрузка умножения длинного и обычного числа. { // Запоминаем длину числа. int xn = x.num.Count; // Переменная для ответа. LongNumber a = new LongNumber(); // В ответе есть ячейка с нулём, удаляем её, чтобы можно было работать только с методом Add. a.num.RemoveAt(0); // Запоминаем знак короткого числа и меняем это число, если оно меньше нуля, для удобства. int sign; if (y >= 0) { sign = 1; } else { sign = -1; y *= -1; } // Переменные для текущего результата и переноса. int b = 0; int p = 0; // Если входное число меньше 10. if (y / 10 == 0) { // Умножаем его на длинное. for (int i = 0; i < xn; i++) { b = x.num[i] * y + p; p = b / 10; a.num.Add(b % 10); } // Если после умножения остался перенос, записываем его в новую ячейку. if (p > 0) { a.num.Add(p); } // Записываем знак. a.sign = x.sign * sign; } // Если входное число из нескольких цифр. else { // Превращаем его в длинное и считаем произведение длинных. string s = Convert.ToString(y); LongNumber y0 = new LongNumber(s); a.EqualTo(x * y0); } a.exp = x.exp; // Удаляем нули и возвращаем. a.RemoveZeros(); return(a); }
public LongNumber Abs(LongNumber x) // Метод, возвращающий модуль числа. { // Переменная для ответа. LongNumber a = new LongNumber(); // Присваиваем, чтобы не менять исходную переменную. a.EqualTo(x); // Возвращаем модуль знака и возвращаем число. a.sign = Math.Abs(a.sign); return(a); }
public static LongNumber Task13(LongNumber x) // Задача номер ТРИНАДЦАТЬ! { // Переменная для ответа. LongNumber a = new LongNumber(); // Длинная единица, для удобства. LongNumber b = new LongNumber("1"); // Если модуль икса больше единицы. if (x.Abs(x) > b) { // Возвращаем ноль. return(a); } // Если всё нормально. else { // Считаем 100 шагов. int n = 100; // Переменная для текущего шага. // Считаем со 2 шага, поэтому изначально она равна первому шагу, то бишь иксу. LongNumber k = new LongNumber("1"); k.EqualTo(x); // Переменная для знака. int p = 1; LongNumber y = new LongNumber("1"); // Считаем ряд со второго шага в цикле. for (int i = 2; i <= n; i += 2) { k.EqualTo(k * x); k.EqualTo(k * x); k.EqualTo(k * p); y.EqualTo(y * (i * (i - 1))); k.EqualTo(k / y); p *= -1; a.EqualTo(a + k); } // Удаляем лишние нули и возвращаем. a.RemoveZeros(); return(a); } }
public static LongNumber operator +(LongNumber x, int y) // Сложение длинного и обычного чисел. { // Переменная для ответа. LongNumber a = new LongNumber(); // Превращаем число в длинное. string s = Convert.ToString(y); LongNumber y1 = new LongNumber(s); // Считаем сумму длинных чисел. a.EqualTo(x + y1); return(a); }
public static LongNumber UpToPow(LongNumber x1, LongNumber y1) // Бинарное возведение в степень. { // Переменная для ответа. LongNumber a = new LongNumber("1"); // "Длинная" единица, для удобства. LongNumber b = new LongNumber("1"); // Сохраняем входные данные, т.к., возможно, будем их менять. LongNumber x = new LongNumber(); x.EqualTo(x1); LongNumber y = new LongNumber(); y.EqualTo(y1); a.EqualTo(x); // Если степень целая, считаем. if (y.exp == 0) { if ((y.num.Count == 1) && (y.num[0] == 0)) { return(b); } if (y.num[0] % 2 == 1) { y.EqualTo(y - b); y.EqualTo(UpToPow(x, y)); y.EqualTo(y * x); return(y); } else { y.EqualTo(y / 2); a.EqualTo(UpToPow(x, y)); a.EqualTo(a * a); return(a); } } // Удаляем лишние нули и возвращаем. a.RemoveZeros(); return(a); }
public static LongNumber operator *(LongNumber x1, LongNumber y1) // Перегрузка умножения длинных чисел. { // Создаём переменную для ответа. LongNumber a = new LongNumber(); // Сохраняем входные переменные, т.к., возможно, будем их позже менять. LongNumber x = new LongNumber(); x.EqualTo(x1); LongNumber y = new LongNumber(); y.EqualTo(y1); // Запоминаем длины чисел. int xn = x.num.Count, yn = y.num.Count; // Переменная для текущего результата. LongNumber n = new LongNumber(); n.EqualTo(y * x.num[0]); a.EqualTo(a + n); // Перебираем цифры в первом числе. for (int i = 1; i < xn; i++) { // Умножаем цифру первого числа на второе. n.EqualTo(y * x.num[i]); // Сдвигаем текущий результат на позицию цифры. for (int j = 0; j < i; j++) { n.num.Insert(0, 0); } // Складываем с ответом. a.EqualTo(a + n); } // Экпонента ответа - сумма экспонент. a.exp = x.exp + y.exp; // Удаляем лишние нули. a.RemoveZeros(); // Перемножаем знаки и возвращаем. a.sign = x.sign * y.sign; return(a); }
static void Main(string[] args) { LongNumber a = new LongNumber(); Console.WriteLine("В этой программке работают 1, 4, 6, 7, 10, 13 и 16 задачи."); Console.WriteLine("Введите число К для первой задачи."); int k = Convert.ToInt32(Console.ReadLine()); a.EqualTo(Task1(k)); Console.WriteLine("Сиё есть 1 задача."); a.WriteOut(); Console.WriteLine("Введите два длинных числа для 4 задачи."); string s = Console.ReadLine(); string s1 = Console.ReadLine(); LongNumber x1 = new LongNumber(s); LongNumber y1 = new LongNumber(s1); a.EqualTo(x1 * y1); Console.WriteLine("Сиё есть умножение."); a.WriteOut(); a.EqualTo(x1 / y1); Console.WriteLine("Сиё есть деление."); a.WriteOut(); Console.WriteLine("Введите число знаков для шестой задачи."); k = Convert.ToInt32(Console.ReadLine()); a.EqualTo(Task6(k)); a.WriteOut(); Console.WriteLine("Введите число знаков для седьмой задачи."); k = Convert.ToInt32(Console.ReadLine()); a.EqualTo(Task7(k)); a.WriteOut(); Console.WriteLine("Введите основание и степень для 10 задачи."); s = Console.ReadLine(); s1 = Console.ReadLine(); x1 = new LongNumber(s); y1 = new LongNumber(s1); a.EqualTo(Task10(x1, y1)); Console.WriteLine("Сиё есть 10 задача."); a.WriteOut(); Console.WriteLine("Введите число Х для тринадцатой задачи."); s = Console.ReadLine(); x1 = new LongNumber(s); a.EqualTo(Task13(x1)); Console.WriteLine("Сиё есть 13 задача."); a.WriteOut(); Console.WriteLine("Сиё есть 16 задача."); Task16(); }
public static LongNumber Task1(int k) // Задача номер ОДИН! { // Переменные для ответа. LongNumber a = new LongNumber("1"); LongNumber x = new LongNumber("1"); // Дополнительная переменная. int p; // Собственно, сам счёт. for (int i = 2; i <= k; i++) { p = i * i; x.EqualTo(a * p); a.EqualTo(a + x); } // Возвращаем. a.RemoveZeros(); return(a); }
public static LongNumber operator /(LongNumber x1, LongNumber y1) { // Переменная для ответа. LongNumber a = new LongNumber(); // Сохраняем входные переменные, т.к., возможно, будем их позже менять. LongNumber x = new LongNumber(); x.EqualTo(x1); LongNumber y = new LongNumber(); y.EqualTo(y1); // Запоминаем длины чисел. int xn = x.num.Count, yn = y.num.Count; // Переменная для переноса. int p = 0; // Если у второго числа есть дробная часть. if (y.exp > 0) { // Если у первого она не меньше, двигаем оба, пока второе не станет целым. if (x.exp >= y.exp) { x.exp -= y.exp; y.exp = 0; } // Если у первого она меньше, добавляем нули и двигаем оба. else { for (int i = 0; i < y.exp - x.exp; i++) { x.num.Insert(0, 0); xn++; } y.exp = 0; x.exp = 0; } } // Разность длин чисел. int c = xn - yn; // Двигаем левое число до конца правого, если оно короче, с запоминанием исходной позиции. for (int i = 0; i < c - 1; i++) { y.num.Insert(0, 0); } // p = x.num[xn - 1]; // Переменная для сохранения предыдущего результата. LongNumber q = new LongNumber(); // Переменная для проверки длины чисел. LongNumber w = new LongNumber(); // Флаг для проверки. bool b = true; // Переменная для ранения текущей позиции запятой. int e = 0; // Переменная для сохранения точности. int e1 = x.maxexp; // Пока не дошли до удвоенной точности. while ((b) && (e <= x.maxexp * 2)) { // Пока первое число не меньше второго, вычитаем из него второе. while (!(x < y)) { x.EqualTo(x - y); a.PlusOne(); } // Если первое число превратилось в ноль. if ((x.num.Count == 1) && (x.num[0] == 0)) { // Если второе число всё ещё сдвинуто, добавляем нужное число нулей и выходим из цикла. if (y.num.Count > yn) { for (int j = 0; j < yn; j++) { a.num.Insert(0, 0); } } break; } // Если первое не ноль и второе сдвинуто, двигаем второе на один разряд обратно. if (y.num.Count > yn) { y.num.RemoveAt(0); } // Если первое не ноль и второе не сдвинуто. else { // Увеличиваем позицию запятой в ответе. e++; // Если не дошли до указанной точности, добавляем ноль в первое число. if (e <= e1) { x.num.Insert(0, 0); } // Если дошли. else { // Сравниваем значения текущего и предыдущего шагов. w.EqualTo(a - q); // Идём с позиции запятой до указанной точности. int j = x.num.Count; while (j >= e1) { // Если есть не ноль в разности, выходим из цикла. if (w.num[j - 1] != 0) { break; } j--; } // Если дошли до указанной точности, // то бишь, в разности текущего и предыдущего все нули, // то бишь, разряды текущего шага до указанной точности не изменились, // выходим из цикла. if (j <= e1) { break; } } } // Сохраняем значение текущего шага. q.EqualTo(a); // Добавляем разряд в ответ. a.num.Insert(0, 0); } // Записываем экспоненту в ответ. a.exp = e + x.exp; // Записываем знак в ответ и возвращаем. a.sign = x.sign * y.sign; return(a); }
public static LongNumber operator /(LongNumber x1, int y) // Перегрузка деления. { // Переменная ддля ответа. LongNumber a = new LongNumber(); // Сохраняем входные переменные, т.к., возможно, будем их позже менять. // Интовое число не сохраняем, т.к. оно передаётся по значению и исходное меняться не будет. LongNumber x = new LongNumber(); x.EqualTo(x1); // Запоминаем длину. int xn = x.num.Count; // Переменные для текущего результата и переноса. int b = 0; int p = 0; // Если короткое число меньше нуля, меняем его знак. Знак ответа противоположен знаку первого числа. if (y < 0) { a.sign = x.sign * (-1); y *= -1; } // Иначе знак ответа равен знаку первого числа. else { a.sign = x.sign; } // Если во втором числе одна цифра. if (y / 10 == 0) { // Делаем ответ полностью пустым, для удобства. a.num.RemoveAt(0); // Делим первое число на второе, результат(одна цифра) вставляем в начало ответа. for (int i = xn - 1; i >= 0; i--) { b = p * 10 + x.num[i]; p = b % y; b /= y; a.num.Insert(0, b); } // Записываем эспоненту ответа. a.exp = x.exp; // Если остался перенос, считаем до 15 знака после запятой. if (p > 0) { while ((a.exp < x.maxexp) && (p != 0)) { b = p * 10; p = b % y; b /= y; a.num.Insert(0, b); a.exp++; } } } // Если во втором числе больше 1 цифры, делаем его длинным и считаем частное длинных чисел. else { string s = Convert.ToString(y); x = new LongNumber(s); a.EqualTo(x1 / x); } // Удаляем лишние нули и возвращаем. a.RemoveZeros(); return(a); }
public static bool operator >(LongNumber x1, LongNumber y1) // Перегрузка сравнения 1. { // Сохраняем входные переменные, т.к., возможно, будем их позже менять. LongNumber x = new LongNumber(); x.EqualTo(x1); LongNumber y = new LongNumber(); y.EqualTo(y1); // Переменная для ответа. bool b = false; // Если знак первого меньше, то ложь. if (x.sign < y.sign) { return(false); } // Если знак второго меньше - истина. else if (x.sign > y.sign) { return(true); } // Знаки равны, теперь если у первого длиннее целая часть - истина. if (x.num.Count - x.exp > y.num.Count - y.exp) { return(true); } // Если короче - ложь. else if (x.num.Count - x.exp < y.num.Count - y.exp) { return(false); } // Целые части одинаковой длины. else { // Приводим оба числа к одному количеству знаков, добавляя нули в более короткое. int c = Math.Abs(x.exp - y.exp); if (x.exp > y.exp) { for (int i = 0; i < c; i++) { y.num.Insert(0, 0); } } else if (x.exp < y.exp) { for (int i = 0; i < c; i++) { x.num.Insert(0, 0); } } // Перебираем все цифры. for (int i = 0; i < x.num.Count; i++) { // Если цифра первого числа больше цифры того же разряда второго числа, флаг - истина. if (x.num[i] > y.num[i]) { b = true; } // Если меньше - ложь. Равенство не меняет флаг. if (x.num[i] < y.num[i]) { b = false; } } // Возвращаем ответ. return(b); } }
public static LongNumber operator -(LongNumber x1, LongNumber y1) // Перегрузка оператора вычитанияы { // Создаём переменную для ответа. LongNumber a = new LongNumber(); // Сохраняем входные переменные, т.к., возможно, будем их позже менять. LongNumber x = new LongNumber(); x.EqualTo(x1); LongNumber y = new LongNumber(); y.EqualTo(y1); // Запоминаем длины чисел. int xn = x.num.Count, yn = y.num.Count; // Если уменьшаемое короче, делаем так: x-y=-y+x=-(y-x). if (xn - x.exp < yn - y.exp) { x.sign *= -1; y.sign *= -1; a.EqualTo(y - x); a.RemoveZeros(); return(a); } // Проверяем равенство знаков. if (x.sign == y.sign) { // Переменные для текущего результата и переноса. int b = 0; int p = 0; // Удаляем все ячейки в переменной ответа. a.num.RemoveAt(0); // Разница в длинах дробных частей. int c = Math.Abs(x.exp - y.exp); // Сравниваем длины дробных частей. if (x.exp >= y.exp) { // Если первое не короче второго (дробная часть), перепысываем более длинную часть в ответ. for (int i = 0; i < c; i++) { a.num.Add(x.num[i]); } // Считаем общую часть. for (int i = c; i < Math.Min(xn, yn + c); i++) { b = x.num[i] - y.num[i - c] - p; // Если текущий результат меньше нуля, добавляем к нему основание и занимаем единицу. if (b < 0) { b += 10; p = 1; } else { p = 0; } a.num.Add(b); } // Уменьшаемое не короче вычитаемого, поэтому считаем более длинную часть, если она есть. for (int i = yn + c; i < xn; i++) { b = x.num[i] - p; if (b < 0) { b += 10; p = 1; } else { p = 0; } a.num.Add(b); } // Записываем в ответ экспоненту. a.exp = x.exp; } else { // Если у второго длинная часть больше, вычитаем более длинную часть из нулей. for (int i = 0; i < c; i++) { b = 10 - p - y.num[i]; p = 1; a.num.Add(b); } // Считаем общую часть. for (int i = c; i < yn; i++) { b = x.num[i - c] - y.num[i] - p; if (b < 0) { p = 1; b += 10; } else { p = 0; } a.num.Add(b); } // Уменьшаемое не короче вычитаемого, поэтому считаем более длинную часть, если она есть. for (int i = yn - c; i < xn; i++) { b = x.num[i] - p; if (b < 0) { p = 1; b += 10; } else { p = 0; } a.num.Add(b); } a.exp = y.exp; } // Записываем знак. a.sign = y.sign; // Проверяем, осталось ли что-то в переносе. if (p > 0) { // Если осталось, вычитаем ответ из старшего разряда и меняем знак. a.RemoveZeros(); p = 0; for (int i = 0; i < a.num.Count; i++) { b = 10 - a.num[i] - p; p = 1; a.num[i] = b; } a.sign *= -1; } } else { // Если знаки не равны, меняем знак и считаем сумму. y.sign *= -1; a.EqualTo(x + y); } // Удаляем лишние нули и возвращаем. a.RemoveZeros(); return(a); }
public static LongNumber operator +(LongNumber x1, LongNumber y1) // Перегрузка оператора сложения. { // Создаём переменную для ответа. LongNumber a = new LongNumber(); // Сохраняем входные переменные, т.к., возможно, будем их позже менять. LongNumber x = new LongNumber(); x.EqualTo(x1); LongNumber y = new LongNumber(); y.EqualTo(y1); // Запоминаем длины чисел. int xn = x.num.Count, yn = y.num.Count; // Проверяем равенство знаков. if (x.sign == y.sign) { // Переменные для текущего результата и переноса. int b = 0; int p = 0; // Удаляем все ячейки в переменной ответа. a.num.RemoveAt(0); // Разница в длинах дробных частей. int c = Math.Abs(x.exp - y.exp); // Сравниваем длины дробных частей. if (x.exp >= y.exp) { // Если длиннее первое, переписываем более длинную часть в ответ. for (int i = 0; i < c; i++) { a.num.Add(x.num[i]); } // Считаем сумму общей части, учитывая, что второе сдвинуто относительно первого // для совпадения позиции запятой. for (int i = c; i < Math.Min(xn, yn + c); i++) { b = x.num[i] + y.num[i - c] + p; a.num.Add(b % 10); p = b / 10; } // Сравниваем длины чисел. if (yn + c >= xn) { // Если второе длиннее, переписываем его в ответ, учитывая перенос. for (int i = xn; i < yn + c; i++) { b = y.num[i - c] + p; a.num.Add(b % 10); p = b / 10; } } else { // Если первое длиннее, переписываем его в ответ, учитывая перенос. for (int i = yn + c; i < xn; i++) { b = x.num[i] + p; a.num.Add(b % 10); p = b / 10; } } // Записываем экспоненту в ответ. a.exp = x.exp; } else { // Если длиннее второе, переписываем более длинную часть в ответ. for (int i = 0; i < c; i++) { a.num.Add(y.num[i]); } // Считаем сумму общей части. for (int i = c; i < Math.Min(xn + c, yn); i++) { b = x.num[i - c] + y.num[i] + p; a.num.Add(b % 10); p = b / 10; } // Сравниваем длины чисел. if (yn >= xn + c) { // Если длиннее второе , переписываем его в ответ, учитывая перенос. for (int i = xn + c; i < yn; i++) { b = y.num[i] + p; a.num.Add(b % 10); p = b / 10; } } else { // Если длиннее первое, переписываем его в ответ, учитывая перенос. for (int i = yn; i < xn + c; i++) { b = x.num[i - c] + p; a.num.Add(b % 10); p = b / 10; } } // Записываем экспоненту в ответ. a.exp = y.exp; } // Записывем знак. a.sign = x.sign; } // Если знаки не равны, меняем один и считаем разность. else { y.sign *= -1; a.EqualTo(x - y); } // Удаляем лицние нули, если они есть. a.RemoveZeros(); // Возвращаем ответ. return(a); }