Как можно улучшить функцию суммирования двоичных чисел?
Я сделал функцию которая принимает два двоичных числа которые находиться в string и суммирует их. Правильно ли я сделал эту функцию с точки зрения переменных например или можно лучше сделать? P.s сама функция работает корректно
public string res = "";
public void SumBit(string bite1,string bite2)
{
string res = "";
char interBit = '0';
for (int i=bite1.Length-1 ;i>=0; i--)
{
if (bite1[i] == '1' && bite2[i] == '1')
{
if (interBit == '1')
{
res = '1' + res;
}
else
{
res = '0' + res;
interBit = '1';
}
}
else
if (bite1[i] == '1' && bite2[i] == '0' || bite1[i] == '0' && bite2[i] == '1')
{
if (interBit == '1')
{
res = '0' + res;
}
else
{
res = '1' + res;
}
}
else
{
if (interBit=='1')
{
res = '1' + res;
interBit = '0';
}
else
res = '0' + res;
}
}
}
Я использовал тип string, потому что удобно работать ведь какое либо десятичное число легко перевести в двоичное следующим образом
number = Convert.ToString(intput, 2);
Ответы (2 шт):
Вообще такое делать имеет смысл только в учебных целях, в реальной задаче лучше строку перевести в число, сложить и обратно перевести в строку.
Но мне просто было интересно написать алгоритм, потому скидываю как ответ, чего добру пропадать то.
Я вместо кучи if-ов просто посчитал количество единичек на каждой из позиций.
public string SumBit(string bite1,string bite2)
{
bool reminder = false;
var ret = new Stack<char>();
var len = Math.Max(bite1.Length, bite2.Length);
for(int i=0; i<len; i++)
{
int cnt = reminder ? 1 : 0;
if (i < bite1.Length && bite1[bite1.Length - 1 - i] == '1') cnt++;
if (i < bite2.Length && bite2[bite2.Length - 1 - i] == '1') cnt++;
if (cnt % 2 != 0) ret.Push('1');
else ret.Push('0');
reminder = cnt > 1;
}
if(reminder) ret.Push('1');
var sb = new StringBuilder();
while(ret.Count > 0) sb.Append(ret.Pop());
return sb.ToString();
}
Проверка
Console.WriteLine(SumBit("1010","0101"));
Console.WriteLine();
Console.WriteLine(SumBit("00","00"));
Console.WriteLine(SumBit("00","01"));
Console.WriteLine(SumBit("00","10"));
Console.WriteLine(SumBit("00","11"));
Console.WriteLine();
Console.WriteLine(SumBit("01", "00"));
Console.WriteLine(SumBit("01", "01"));
Console.WriteLine(SumBit("01", "10"));
Console.WriteLine(SumBit("01", "11"));
Console.WriteLine();
Console.WriteLine(SumBit("10", "00"));
Console.WriteLine(SumBit("10", "01"));
Console.WriteLine(SumBit("10", "10"));
Console.WriteLine(SumBit("10", "11"));
Console.WriteLine();
Console.WriteLine(SumBit("11", "00"));
Console.WriteLine(SumBit("11", "01"));
Console.WriteLine(SumBit("11", "10"));
Console.WriteLine(SumBit("11", "11"));
Результат
1111
00
01
10
11
01
10
11
100
10
11
100
101
11
100
101
110
Тоже раньше писал такие же решения, как @tym32617:
public string AddBinary(string a, string b)
{
var sb = new StringBuilder();
var carry = 0;
var iA = a.Length - 1;
var iB = b.Length - 1;
while (iA >= 0 || iB >= 0)
{
var bA = iA < 0 ? 0 : a[iA] - '0';
var bB = iB < 0 ? 0 : b[iB] - '0';
sb.Insert(0, (bA + bB + carry) % 2);
carry = (bA + bB + carry) / 2;
iA--;
iB--;
}
if(carry == 0)
return sb.ToString();
sb.Insert(0, '1');
return sb.ToString();
}
Но мне не нравится вот эта последняя проверка переноса, её можно упростить:
public string AddBinary(string a, string b)
{
var sb = new StringBuilder();
var carry = 0;
var iA = a.Length - 1;
var iB = b.Length - 1;
while (iA >= 0 || iB >= 0 || carry > 0)
{
var bA = iA < 0 ? 0 : a[iA] - '0';
var bB = iB < 0 ? 0 : b[iB] - '0';
sb.Insert(0, (bA + bB + carry) % 2);
carry = (bA + bB + carry) / 2;
iA--;
iB--;
}
return sb.ToString();
}
Задача взята с литкода: https://leetcode.com/problems/add-binary/
[Test]
[TestCase("11", "1", "100")]
[TestCase("1010", "1011", "10101")]
public void SolutionTests(string a, string b, string expected)
{
var actual = new Solution().AddBinary(a, b);
Assert.That(actual, Is.EqualTo(expected));
}
Для десятичных чисел алгоритм тот же, надо только % 2 и / 2 заменить на основание 10. И это проще в написании потому что универсальнее.
public string AddStrings(string num1, string num2)
{
var res = new StringBuilder();
int carry = 0;
int p1 = num1.Length - 1;
int p2 = num2.Length - 1;
while (p1 >= 0 || p2 >= 0 || carry != 0)
{
int x1 = p1 >= 0 ? num1[p1] - '0' : 0;
int x2 = p2 >= 0 ? num2[p2] - '0' : 0;
int value = (x1 + x2 + carry) % 10;
carry = (x1 + x2 + carry) / 10;
res.Insert(0, value);
p1--;
p2--;
}
return res.ToString();
}