0

Вот мой проект:

https://gitlab.com/IlyaKvashnin/Calculator

Нужно реализовать сложение в произвольной системе счисления. Я начал в классе "Addition", но даже нет мыслей как это реализовать. Калькулятор должен складывать числа в произвольной системе счисления, показывая переносы, прошу хотя бы натолкнуть на мысль с чего начать

    using System;
    namespace Calculator
    {
        public class Addition
        {
            public void InputNotation()
            {
                Console.WriteLine("Введите систему счисления в которой будет производиться сложение");
                int notation = int.Parse(Console.ReadLine());
            }
        }
    }
  • Что значит "произвольной"? Как вы собираетесь выполнять запись чисел, скажем для системы счисления с основанием 333? А для системы 456778? Или все-таки есть какие-то ограничения? – aepot Jan 11 '22 at 11:28
  • Пусть будет ограничение до 50, но в задание его нет, просто "произвольной" – Ilya Kvashnin Jan 11 '22 at 11:29
  • Окей, для того, чтобы сложить 2 числа в 50-чной системе счисления, надо их как-то ввести сначала. Как вы планируете обозначать цифры числа в такой системе счисления? Уточните у автора задания, что он имел в виду под словом "произвольной". – aepot Jan 11 '22 at 11:36
  • @aepot если бы у меня было на это уточнение время и возможность – Ilya Kvashnin Jan 11 '22 at 11:41
  • 1
    https://ru.stackoverflow.com/a/453060/178988 – Qwertiy Jan 11 '22 at 11:44
  • Я вам сказал, с чего начать - с ограничений по основанию и представлений чисел в произвольной системе счисления. Когда окончательно с этим определитесь, тогда можно будет двигаться к математике. – aepot Jan 11 '22 at 11:46
  • @aepot можно использовать просто таблицу юникода, ограничений так как нет, к сожалению, выбрать можно что угодно, выбрать какие понравятся – Ilya Kvashnin Jan 11 '22 at 11:47
  • 1
    Тогда у вас уже много работы, приступайте. Организуйте ввод чисел, преобразуйте введенное число, скажем в int, сложите 2 инта, это вы умеете, и результат выведите преобразовав обратно в целевую систему. – aepot Jan 11 '22 at 11:51
  • @aepot https://gitlab.com/IlyaKvashnin/Calculator2 все в том же классе "Addition" нашел такой вариант, но не понимаю почему он работает только при вещественном числе – Ilya Kvashnin Jan 11 '22 at 11:57
  • А нет, складывает – Ilya Kvashnin Jan 11 '22 at 11:59
  • Мой вам совет: ограничьтесь целыми числами. Просто поверьте на слово. – aepot Jan 11 '22 at 12:01
  • @aepot Запушил версию без вещественных, просто мне нужно в течение часа, наверное, показать что-то хотя бы – Ilya Kvashnin Jan 11 '22 at 12:05
  • Достаточно, конечно, вопрос в том как задействовать, ситуация в том, что это задание на примерно час и это лишь 1/3 этого задания, я пытаюсь сделать максимум – Ilya Kvashnin Jan 11 '22 at 12:08
  • https://gitlab.com/IlyaKvashnin/Calculator2 – Ilya Kvashnin Jan 11 '22 at 12:20
  • Ну вроде это работает до 16ричной СС, только нужно теперь переводить в произвольную ответ, вообще нужно чтобы было сложение прям допустим чисел 77 в восьмеричной и 465 тоже в восьмеричной, но пытаюсь сделать хоть какую-то реализацию – Ilya Kvashnin Jan 11 '22 at 12:21
  • @aepot Я запушил снова код, если я правильно понимаю, сейчас я увеличу case и тем самым расширю системы счисления, но как теперь перевести из десятичной в другую – Ilya Kvashnin Jan 11 '22 at 12:24
  • правилами ресурса запрещено дублировать свои вопросы. Это некрасиво по отношению к другим пользователям. – Andrew Stop_RU_war_in_UA Jan 11 '22 at 13:44

1 Answers1

2

По идее, из обычного курса информатики известны алгоритмы для перевода из десятичной СС в произвольную и из произвольной в десятичную. Надеюсь, что по заданию нет необходимости переводить отрицательные и дробные числа, поэтому приведу пример для целых беззнаковых. Если ими воспользоваться, то можно сделать что-то вроде таких методов:

//Пример для 23F в шестнадцатеричной: 2 * 16^2 + 3 * 16 + 15 * 16^0 = 512 + 48 + 15 = 575 в десятичной.
public static ulong ToDecimal(string number, uint systemBase)
{
    //Допустим, что лимитом для СС будет 36, чтобы обойтись латинскими символами для сохранения.
    if (systemBase > 36 || systemBase < 2) throw new ArgumentOutOfRangeException("Основание системы счисления слишком велико для сохранения латинскими символами, либо слоишком мало для операций.");
    ulong result = 0;
    int position = number.Length - 1;
    foreach (char c in number)
    {
        //Пусть в этой переменной будет значение символа.
        int charValue = 0;
        if (c >= '0' && c <= '9')//Если это десятичная цифра, то сохраняем как есть.
        {
             charValue = int.Parse(c.ToString());
        }
        else if (char.ToLower(c) >= 'a' && char.ToLower(c) <= 'z')//Для латинской буквы будет величина, начиная с 10.
        {
             charValue = char.ToLower(c) - 'a' + 10;
        }
        else throw new ArgumentException("В записи числа содержатся недопустимые символы.");
        result += (ulong)charValue * (ulong)Math.Pow(systemBase, position--);//Добавляем значение.
    }
    return result;
}
//Ну и тут есть похожий алгоритм. Делим число на основание СС и записываем остатки от деления в обратном порядке.
public static string FromDecimal(ulong value, uint systemBase)
{
    //Аналогичная проверка.
    if (systemBase > 36 || systemBase < 2) throw new ArgumentOutOfRangeException("Основание системы счисления слишком велико для сохранения латинскими символами, либо слоишком мало для операций.");
    string result = "";
    do//Пока от числа хоть что-то осталось:
    {
        ushort remainder = (ushort)(value % systemBase);//находим остаток
        if (remainder >= 0 && remainder <= 9) 
        {
            //Если он десятичный, то добавим цифру в начале строки с ответом
            result = remainder + result;
        }
        else
        {
            //Иначе добавим какую-нибудь латинскую букву.
            result = (char)(remainder - 10 + 'a') + result;
        }
        value /= systemBase;
   }
   while (value > 0);
   return result;
}

Понятно, что ulong я взял для примера (потому что понятия не имею, какие по длине числа вы собираетесь переводить).Данные методы нормально принимают и заглавные и строчные символы, но на выходе выдают строчные. Если нужно добавить больше символов, то делаете дополнительное условие, и переводите по тому же алгоритму. Так как char является числом от 0 до 65535, его можно использовать в математических операциях.
Что насчёт сложения и вычитания — можно перевести в десятичную, посчитать в десятичной, а потом перевести в нужную СС.

  • Проблема в том, что нужно выполнять сложение "стобликом" как оказалось – Ilya Kvashnin Jan 11 '22 at 13:47
  • 1
    А, ну тогда можно брать значения символов (где у меня первый метод, условия в нём), и их складывать, а если они превышают основание СС, то переносить в следующий разряд. По идее, тут целый класс/структуру можно для этого написать – IOException Jan 11 '22 at 15:01