При сложении двух двоичных чисел


Я хочу улучшить этот код лучше с логикой и с использованием STL.

#include <iostream>
#include <vector>

void addition(const std::vector<int>& A,
              const std::vector<int>& B,
                    std::vector<int>& C)
{
   int size_A = A.size();
   int size_B = B.size();
   int max_size;
   if (size_A >= size_B)
   {
      max_size = size_A;
   }
   else
   {
      max_size = size_B;
   }

   int carry = 0, sum = 0;

   int i = size_A - 1, j = size_B - 1, k = max_size;
   C.resize(k + 1);

   while ( i >= 0 && j >= 0 && k >= 0)
   {
      sum = A[i] + B[j] + carry;

      if (sum == 0)
      {
         carry = 0;
         C[k] = 0;
      }
      else if (sum == 1)
      {
         carry = 0;
         C[k] = 1;
      }
      else if (sum == 2)
      {
         carry = 1;
         C[k] = 0;
      }
      else if (sum == 3)
      {
         carry = 1;
         C[k] = 1;
      }
      i--;
      j--;
      k--;
   }
  //if size of first binary number is greter than first
  if (max_size == size_A)
  {
     while (i >= 0 && k >= 0)
     {
        sum = A[i] + carry;

        if (sum == 0)
        {
           carry = 0;
           C[k] = 0;
        }
        else if (sum == 1)
        {
           carry = 0;
           C[k] = 1;
        }
        else if (sum == 2)
        {
           carry = 1;
           C[k] = 0;
        }
        else if (sum == 3)
        {
           carry = 1;
           C[k] = 1;
        }
        i--;
        k--;
     }
  }
  //If size of second binary number is greater than first
  else if (max_size == size_B)
  {
     while (j >= 0 && k >= 0)
     {
       sum = B[j] + carry;

       if (sum == 0)
       {
          carry = 0;
          C[k] = 0;
       }
       else if (sum == 1)
       {
          carry = 0;
          C[k] = 1;
       }
       else if (sum == 2)
       {
          carry = 1;
          C[k] = 0;
       }
       else if (sum == 3)
       {
          carry = 1;
          C[k] = 1;
       }
       j--;
       k--;
     }
  }
  C[0] = carry;
}

int main()
{
   int n1, n2, val;
   std::cout << "Enter the  number of bits for first binary numbers \n";
   std::cin >> n1;
   std::cout << "Enter the  number of bits for second binary numbers \n";
   std::cin >> n2;

   std::vector<int> A;
   std::vector<int> B;
   std::vector<int> C;

   std::cout << "Enter bits for first binary number \n";
   for (int i = 0; i < n1; i++)
   {
      std::cin >> val;
      A.push_back(val);
   }

   std::cout << "Enter bits for second binary number \n";
   for (int i = 0; i < n2; i++)
   {
     std::cin >> val;
     B.push_back(val);
   }

   std::cout << "First number    : ";
   for (int i = 0; i < A.size(); i++)
   {
      std::cout << A[i];
   }

   std::cout << "\nSecond number   : ";
   for (int i = 0; i < B.size(); i++)
   {
      std::cout << B[i];
   }

   addition(A, B, C);

   std::cout << "\nResult          : ";
   for (int i = 0; i < C.size(); i++)
   {
     std::cout << C[i];
   }
   std::cout << "\n";
}


981
4
c++
задан 12 февраля 2018 в 06:02 Источник Поделиться
Комментарии
3 ответа

Писать сухой код:

Сухой - не повторяйся.

std::cout << "Enter bits for first binary number \n";
for (int i = 0; i < n1; i++)
{
std::cin >> val;
A.push_back(val);
}

std::cout << "Enter bits for second binary number \n";
for (int i = 0; i < n2; i++)
{
std::cin >> val;
B.push_back(val);
}

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

Высокий бит-это где?

  std::cin >> val;
B.push_back(val);

С помощью этого кода самый старший бит находится в ячейке 0. Это дает вам комнату, чтобы расширить количество. Поместите наименьший значащий бит в 0 и более значимых битов на более высоких местах. Это позволит сделать его легче сделать операции стандартные математике в долгосрочной перспективе.

Это похоже на переключатель:

  if (sum == 0)
{
carry = 0;
C[k] = 0;
}
else if (sum == 1)
{
carry = 0;
C[k] = 1;
}
else if (sum == 2)
{
carry = 1;
C[k] = 0;
}
else if (sum == 3)
{
carry = 1;
C[k] = 1;
}

Я бы написал так:

  switch (sum) {
case 0: carry = 0;C[k] = 0;break;
case 1: carry = 0;C[k] = 1;break;
case 2: carry = 1;C[k] = 0;break;
case 3: carry = 1;C[k] = 1;break;
default: throw std::exception("Something very wrong happened");
}

Еще один случай сухой:

  while ( i >= 0 && j >= 0 && k >= 0)
{
sum = A[i] + B[j] + carry;
// STUFF
k--;i--;j--;
}
//if size of first binary number is greter than first
if (max_size == size_A)
{
while (i >= 0 && k >= 0)
{
sum = A[i] + carry;
// STUFF
k--;i--;
}
}
//If size of second binary number is greater than first
else if (max_size == size_B)
{
while (j >= 0 && k >= 0)
{
sum = B[j] + carry;
// STUFF
k--;j--;
}
}

Не только все "вещи" по факторизовали в собственную функцию. Но эти три петли могут быть объединены в единый цикл.

  for(;k >= 0;--k)
{
int a = (i > 0) ? A[i--] : 0
int b = (j > 0) ? B[j--] : 0;
sum = a + b + carry;
// STUFF
}

5
ответ дан 12 февраля 2018 в 06:02 Источник Поделиться

Организации Код

Вместо нескольких фрагментов кода, которые выполняются условно, в зависимости от того, является ли a меньше, чем B или наоборот, я бы для начала найти меньший и больший из двух входных сигналов, а затем работать на них (независимо от того, были ли они первоначально A или B).

Вернуть то, что создано

Я бы тоже есть Addition возвращать результат, который он создает. Дни, требующие, чтобы избежать возвращения большого значения, чтобы избежать ненужного копирования очень немного древней истории, лучше забыть.

Использовать глаголы при необходимости

Вы addition действительно должны быть add--Вы имеете дело с функцией. Он делает что-то, настолько соответствующего вида работ, чтобы использовать в качестве его имя-глагол.

Магазин младший байт данных

Большую часть времени, это значительно упрощает работу с данными, хранящимися с прямым порядком байтов. То есть, наименее значимый бит хранится в виде 0 элемент каждого вектора, элемент 1 является более значительным, вплоть до максимальной подстрочный хранения наиболее значимый бит этого числа.

Использовать функции, где это уместно

Сейчас твоя main есть несколько строк кода, чтобы прочитать в некоторых битов, выписать некоторые биты, и так далее. По крайней мере, ИМО, каждый из этих кусков кода должна стать функция.

std::string show(std::vector<int> const &t) {
std::string ret;
for (auto p = t.rbegin(); p != t.rend(); p++)
ret += *p ? '1' : '0';
return ret;
}

std::vector<int> read_bin(std::string_view const &prompt, int size) {
std::vector<int> ret;
std::cout << prompt << ": ";

for (int i = 0; i < size; i++)
{
int val;
std::cin >> val;
ret.push_back(val);
}
return { ret.rbegin(), ret.rend() };
}

Использование Соответствующей Логики

Сейчас ты реализации также зависит от наличия того оператора, который уже знает, как добавить две биты и создать проводить на следующий бит из них. Другими словами, ваша реализация зависит от предсуществовании именно то, что он должен реализовать. К сожалению, задача не так проста, как комментарий @TobySpeight будет, как правило, подразумевают. В то время как он почти правильный, что результат можно использовать xorон должен быть 3-полосные операции XOR, а не только два пути (входы предыдущей носить с собой, [I] и B[я]).

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

carry = (A[i] & B[i]) | (A[i] & carry) | (B[i] & carry);

Одна из возможностей это может показаться очевидным было бы просто подсчитывать результаты из трех подвыражений есть-но это возвращает нас к дополнение в зависимости от того, так считая это просто дополнение в маскировке.

Рассмотрите возможность использования класса для хранения и манипулирования ряд

Вместо того, чтобы add, read_bin и show для работы с данными в пару векторов, можно создать класс, который хранит данные, и осуществляет операции с числами с помощью обычного конвенций (+ добавить << для отображения, >> читать.

class binary {
std::vector<int> data;

int &operator[](std::size_t index) { return data[index]; }
int const &operator[](std::size_t index) const { return data[index]; }
public:
auto size() const { return data.size(); }

binary() = default;

binary(size_t size) : data(size) {}

friend std::ostream &operator<<(std::ostream &os, binary const &t) {
std::string ret;
for (auto p = t.data.rbegin(); p != t.data.rend(); p++)
ret += *p ? '1' : '0';
return os << ret;
}

friend std::istream &operator>>(std::istream &is, binary &b) {
std::vector<int> ret;
b.data.resize(is.width());

for (auto p = b.data.rbegin(); p != b.data.rend(); p++) {
int val;
is >> val;
*p = val ? 1 : 0;
}
return is;
}

friend binary operator+(binary const &A, binary const &B) {
binary const &smaller = A.size() < B.size() ? A : B;
binary const &larger = &smaller == &A ? B : A;

binary ret(larger.size() + 1);

int carry = 0;
int sum;
int i;

for (i = 0; i < smaller.size(); i++) {
sum = smaller[i] ^ larger[i] ^ carry;
carry = (smaller[i] & larger[i]) | (smaller[i] & carry) | (larger[i] & carry);

ret.data[i] = sum;
}

for (; i < larger.size(); i++) {
ret.data[i] = larger[i] ^ carry;
carry &= larger[i];
}
return ret;
}
};

Используя эти наши main становится более управляемым, а также:

int main() {
int n1, n2, val;
std::cout << "Enter the number of bits for first binary numbers \n";
std::cin >> n1;
std::cout << "Enter the number of bits for second binary numbers \n";
std::cin >> n2;

std::cout << "Enter bits for first number: ";
binary A;
std::cin >> std::setw(n1) >> A;

std::cout << "Enter bits for second number: ";
binary B;
std::cin >> std::setw(n2) >> B;

auto C = A + B;
auto width = C.size();

std::cout << std::setw(15) << "First number: " << std::setw(width) << A << "\n";
std::cout << std::setw(15) << "Second number: " << std::setw(width) << B << "\n";
std::cout << std::setw(15) << "Sum: " << std::setw(width) << C << "\n";
}

5
ответ дан 13 февраля 2018 в 02:02 Источник Поделиться

В дополнение к другим ответы, я добавлю замену

if (sum == 0)
{
carry = 0;
C[k] = 0;
}
else if (sum == 1)
{
carry = 0;
C[k] = 1;
}
else if (sum == 2)
{
carry = 1;
C[k] = 0;
}
else if (sum == 3)
{
carry = 1;
C[k] = 1;
}

с

C[k]  = sum % 2;
carry = sum / 2;

или, возможно, лучше:

C[k]  = sum & 1;
carry = (sum & 2) >> 1;

1
ответ дан 14 февраля 2018 в 03:02 Источник Поделиться