Разработать класс ДлинноеЧисло, перегрузив определенные операции - C#
Формулировка задачи:
Ребята, правда, поймите и помилуйте! У меня уже идет сессия и по сишарпу осталось сдать последную прогу на длинную арфиметику. Ничего не успеваю и плохо понимаю сишарп Сделайте , пожалуйста.
Хорошо понимаю с++, но синтаксис C# просто убивает!
Разработать класс ДлинноеЧисло, перегрузив следующие операции(если они у вас есть):
a) присваивание;
b) умножение;
c) сложение;
d) вычитание;
e) деление;
f) остаток от деления;
g) операции отношения (сравнения);
решить задачу с целыми неотрицательными длинными числами.
В основной программе создать массив длинных чисел и выполнить его сортировку по возрастанию.
Найти количество делителей n-значного натурального числа (n > 20).
Решение задачи: «Разработать класс ДлинноеЧисло, перегрузив определенные операции»
textual
Листинг программы
public class LongNumber : IComparable<LongNumber>
{
/// <summary>
/// Основание системы счисления
/// </summary>
public const byte BASE = 10;
/// <summary>
/// Цифры числа, начиная с младшего разряда
/// </summary>
List<byte> digits = new List<byte>();
#region Public methods
/// <summary>
/// Удаляет незначащие нули
/// </summary>
public void Normalize()
{
while(digits.Count > 0 && digits[digits.Count - 1] == 0)
digits.RemoveAt(digits.Count -1);
}
/// <summary>
/// Клон
/// </summary>
/// <returns></returns>
public LongNumber Clone()
{
return new LongNumber {digits = new List<byte>(digits)};
}
/// <summary>
/// Сдвиг
/// </summary>
public void Shift(int shift)
{
if (shift > 0)
digits.InsertRange(0, Enumerable.Repeat<byte>(0, shift));
if (shift < 0)
if (-shift >= digits.Count)
digits.Clear();
else
digits.RemoveRange(0, -shift);
}
#endregion
#region Operations
public static LongNumber Add(LongNumber n1, LongNumber n2)
{
var res = new LongNumber();
var count = Math.Max(n1.digits.Count, n2.digits.Count);
var carry = 0;
for (var i = 0; i < count; i++)
{
var sum = n1[i] + n2[i] + carry;
carry = sum / BASE;
sum %= BASE;
res.Add(sum);
}
if (carry > 0)
res.Add(carry);
return res;
}
public static LongNumber Sub(LongNumber n1, LongNumber n2)
{
var res = new LongNumber();
var count = Math.Max(n1.digits.Count, n2.digits.Count);
var carry = 0;
for (var i = 0; i < count; i++)
{
var diff = n1[i] - n2[i] - carry;
carry = 0;
while (diff < 0)
{
diff += BASE;
carry++;
}
res.Add(diff);
}
if (carry > 0) throw new Exception("Negative result");
res.Normalize();
return res;
}
private static LongNumber Mul(LongNumber n, int digit)
{
var res = new LongNumber();
var count = n.digits.Count;
var carry = 0;
for (var i = 0; i < count; i++)
{
var sum = n[i] * digit + carry;
carry = sum / BASE;
sum %= BASE;
res.Add(sum);
}
if (carry > 0)
res.Add(carry);
res.Normalize();
return res;
}
public static LongNumber Mul(LongNumber n1, LongNumber n2)
{
var res = new LongNumber();
var n = n1.Clone();
for(int i=0;i<n2.digits.Count;i++)
{
var digit = n2[i];
res = res + Mul(n, digit);
n.Shift(1);
}
return res;
}
public static void Div(LongNumber n1, LongNumber n2, out LongNumber div, out LongNumber rest)
{
if (n2.digits.Count == 0)
throw new Exception("Zero divide");
//только остаток
if(n1 < n2)
{
div = new LongNumber();
rest = n1.Clone();
return;
}
//выравниваем число знаков
var n = n2.Clone();
var shift = n1.digits.Count - n.digits.Count;
n.Shift(shift);
if (n1 < n)
{
n.Shift(-1);
shift--;
}
//подбираем множитель
var res = n.Clone();
var m = 1;
while (res <= n1)
{
m++;
res = Mul(n, m);
}
m--;
//остаток
rest = n1 - Mul(n, m);
//формируем частное
div = new LongNumber();
div.Add(m);
div.Shift(shift);
//продолжаем деление
if (rest >= n2)
{
LongNumber temp;
Div(rest, n2, out temp, out rest);
div = Add(div, temp);
}
//
div.Normalize();
rest.Normalize();
}
#endregion
#region Routines
int this[int i]
{
get { return i >= digits.Count ? 0 : digits[i]; }
}
void Add(int digit)
{
digits.Add((byte)digit);
}
#endregion
#region Operators
public static LongNumber operator +(LongNumber n1, LongNumber n2)
{
return Add(n1, n2);
}
public static LongNumber operator -(LongNumber n1, LongNumber n2)
{
return Sub(n1, n2);
}
public static LongNumber operator *(LongNumber n1, LongNumber n2)
{
return Mul(n1, n2);
}
public static LongNumber operator /(LongNumber n1, LongNumber n2)
{
LongNumber div, rest;
Div(n1, n2, out div, out rest);
return div;
}
public static LongNumber operator %(LongNumber n1, LongNumber n2)
{
LongNumber div, rest;
Div(n1, n2, out div, out rest);
return rest;
}
public static bool operator >(LongNumber n1, LongNumber n2)
{
return n1.CompareTo(n2) > 0;
}
public static bool operator <(LongNumber n1, LongNumber n2)
{
return n1.CompareTo(n2) < 0;
}
public static bool operator >=(LongNumber n1, LongNumber n2)
{
return n1.CompareTo(n2) >= 0;
}
public static bool operator <=(LongNumber n1, LongNumber n2)
{
return n1.CompareTo(n2) <= 0;
}
public static bool operator ==(LongNumber n1, LongNumber n2)
{
return n1.CompareTo(n2) == 0;
}
public static bool operator !=(LongNumber n1, LongNumber n2)
{
return n1.CompareTo(n2) != 0;
}
#endregion
#region Conversions
public static explicit operator String(LongNumber num)
{
return num.ToString();
}
public static implicit operator LongNumber(string str)
{
return LongNumber.Parse(str);
}
public static LongNumber Parse(string str)
{
var res = new LongNumber();
foreach (var c in str.Reverse())
res.digits.Add(Convert.ToByte(c.ToString(), BASE));
res.Normalize();
return res;
}
#endregion
#region IComparable
public int CompareTo(LongNumber other)
{
var res = digits.Count.CompareTo(other.digits.Count);
if(res == 0)
{
if (digits.Count == 0) return 0;
for (int i = digits.Count - 1; i >= 0 && res == 0; i--)
res = digits[i].CompareTo(other.digits[i]);
}
return res;
}
#endregion
#region Overrided methods
public override bool Equals(object obj)
{
var other = obj as LongNumber;
if (other == null)
return false;
return this == other;
}
public override int GetHashCode()
{
return digits.Sum(b => b);
}
public override string ToString()
{
if (digits.Count == 0)
return "0";
return string.Join("", digits.Reverse<byte>().Select(b => Convert.ToString(b, BASE)));
}
#endregion
}