Проблемы с добавлением двоичных чисел в C без использования массивов / векторов

#c #binary #addition

#c #двоичный #добавление

Вопрос:

Я пытаюсь создать простую программу, которая добавляет 2 двоичных числа, предоставленные пользователем. Я стараюсь не использовать векторы и поэтому использую строки. Вот код, который я получил до сих пор:

 #include <iostream>
#include <string>

int getLonger(std::string a, std::string b) {
    if ((a.size() - '0') >= (b.size() - '0'))
        return 1;
    else
        return 2;
}

int main() {
    std::string n, k, resu<

    std::cout << "Enter first number: ";
    std::cin >> n;
    std::cout << "Enter second number: ";
    std::cin >> k;

    for (int i = 0; i < (getLonger(n, k) == 1 ? n : k).size(); i  ) {
        if ((getLonger(n, k) == 1 ? k : n)[i]) {
            if ((n[i] - '0')   (k[i] - '0') == 2)
                result.insert(0, "10");
            else
                result.insert(0, std::to_string(n[i] - '0'   k[i] - '0'));
        }
    }

    std::cout << resu<
}

  

Я делаю много std::string => int преобразований, которые, как я знаю, не очень хороши, но сейчас это не проблема для меня. Код отлично работает над чем-то вроде 100101 10101 = 111010 , но терпит неудачу на:

1010 11 = -24110 (should be 1101)

и

1 11 = 10 (should be 100)

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

Второе — это мое неправильное добавление 10 , когда 1 1 = 2 — программа не содержит 1. Я попытался исправить это, используя некоторые if statements , но это не сработало правильно.

Я использовал следующий ресурс для понимания двоичного сложения: http://web.math.princeton.edu/math_alive/1/Lab1/BinAdd.html

Как я могу заставить мой скрипт работать правильно?

Комментарии:

1. Ваши getLonger функции кажутся странными. Какой смысл вычитать '0' из размера string s?

2. Несколько комментариев, которые помогут вам найти собственное решение: вы вызываете getLonger несколько раз (дважды в каждом цикле), но вам нужно вызвать его только один раз и сохранить его результат. Было бы лучше обнулить более короткую строку, чтобы вам не нужно было беспокоиться о разной длине. Почему бы вам не выполнить сумму в обратном порядке, а затем инвертировать результат? Таким образом, вам не нужно беспокоиться о каретке (это должно быть значение, которое проверяется в каждом цикле и добавляется при необходимости). Возможно, было бы хорошим упражнением прочитать, как это делают реальные машины (рекомендуемая книга: Code, Чарльз Петцольд)

Ответ №1:

Вот пример решения. Вместо того, чтобы работать со строками, я преобразую числа, чтобы добавлять их как обычно, а затем снова преобразовываю в двоичную строку :

 #include <iostream>
#include <string>
#include <vector>
#include <algorithm>

int str2num(std::string strNumber) {
   int n = 0, i = 0;
   std::string reversed(strNumber.rbegin(), strNumber.rend());
   for(char c : reversed) {
      n  = c - '0' ? 1 << i : 0;
      i  ;
   }
   return n;
}

// Recursive function
void num2str(int n, std::string amp;string, int level) 
{ 
    if (n > 0)  {
        char c = n % 2   '0';
        string  = c; 
        num2str(n >> 1, string, level   1); 
    }
} 

int main() {
    std::string n, k;
    n = std::string("1010");
    k = std::string("11");

    // Conversion in numbers and addition
    int a = str2num(n);
    int b = str2num(k);
    int sum = a   b;
    
    // Conversion to string again
    std::string string("");
    num2str(sum, string, 0);
    std::reverse(string.begin(), string.end());
    std::cout << string << "n";
}
  

Ответ №2:

У меня есть хорошее решение для этого случая.

Я вставил некоторый код javascript, и вы можете перевести на C , если хотите.

Важной структурой данных является FSM, вы можете попытаться очистить этот способ решения такого рода вопросов.

Ваш код подвержен ошибкам и сложен для понимания.

 const str1 = '1010'
const str2 = '11'
const diffLength = Math.abs(str1.length - str2.length);
const fillStr = new Array(diffLength).fill(0).join('');
const [neoStr1, neoStr2] = str1.length > str2.length
    ? [str1, fillStr   str2]
    : [fillStr   str1, str2];

const FSM = {
    0: {
        0: {
            0: [0, 0],
            1: [1, 0]
        },
        1: {
            0: [1, 0],
            1: [0, 1]
        }
    },
    1: {
        0: {
            0: [1, 0],
            1: [0, 1]
        },
        1: {
            0: [0, 1],
            1: [1, 1]
        }
    }
}

const c1 = neoStr1.split('').reverse()
const c2 = neoStr2.split('').reverse()

let carryBit = 0
const result = c1.map((_, i) => {
    const [res, newCarryBit] = FSM[carryBit][c1[i]][c2[i]]
    carryBit = newCarryBit
    return res
}).reverse().join('')

console.log(carryBit ? carryBit   result : result)
  

Комментарии:

1. Проголосовал против, потому что это может запутать пользователя вместо того, чтобы помочь ему понять, что он делает неправильно.