如何在C#中存储两个二进制字符串并使用OR运算符

时间:2015-11-11 23:17:54

标签: c#

输入:

10101
11100

我想将这两个字符串存储在一个数据类型中,以便我可以在这两个字符串上调用| OR运算符。

这是我的代码:

        var g = new byte[2][];

        g[0] = "10101".Select(item => byte.Parse(item.ToString())).ToArray();
        g[1] = "11100".Select(item => byte.Parse(item.ToString())).ToArray();

        //won't compile
        Console.WriteLine(g[0] | g[1]);

我得到的编译器错误是:

无法应用运算符' |'操作数字节[]和字节[]

我也试过BitArray,但这似乎也不对。我尝试了byte.Parse(" 10101")这只会导致溢出,这对我来说很有意义。

我要做的是OR两个字符串的位和结果将= 1,也许我需要移位for循环中的位,我想也许我可以只是OR两个二进制表示匹配长度二进制字符串

显然我选择了错误的数据类型byte []来存储我的二进制字符串,我只是没有足够的经验知道如何用正确的数据类型表示这些二进制字符串。 < / p>

更新

选择正确的答案很困难,因为有多个正确的答案。只是想明确表示这个问题有多种解决方案,这些都是很好的答案。

我的问题是由于我在HackerRank上试图解决的问题:https://www.hackerrank.com/challenges/acm-icpc-team

&#34;您将获得参加ACM-ICPC世界总决赛的N人名单。他们每个人都精通某个主题,或者他们不是。找出2人团队可以了解的最大主题数。并且还要了解有多少团队可以知道最大数量的主题。&#34;

感谢我在Stack Overflow上收到的帮助,我提出了一个不错的解决方案:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

class Solution {
static void Main(String[] args) {
    var inputArr = Console.ReadLine().Split(' ').Select(item => int.Parse(item)).ToArray();
    var n = inputArr[0];
    var m = inputArr[1];


    var g = new byte[n];
    var team = new List<byte>();

    var teamsKnowMax = 0;
    var maxTopics = byte.MinValue >> sizeof(byte) * 8 - m;

    for(var i = 0; i < n; i++){
        g[i] = Convert.ToByte(Console.ReadLine(), 2);
        maxTopics = maxTopics | g[i];
    }

    for(var j = 0; j < n -1; j++){
        for(var k = j+1; k < n; k++){
            var or = g[j] | g[k];
            if((or & maxTopics) == maxTopics)
                teamsKnowMax++;
        }
    }

    Console.WriteLine(Convert.ToString(maxTopics,2).ToCharArray().Count(item => item == '1'));
    Console.WriteLine(teamsKnowMax);
}

}

但我没有考虑约束:

2≤N≤500 
1≤M≤500

所以现在我需要开发一个解决方案,将长二进制字符串分成8位块,就像打破长二进制字符串的字节区域,看看是否有效,而不是通过每个字符字符串。

最初,我开始将大型二进制字符串拆分为8个段,并在有提醒时处理提醒,这创建了一个我无法管理的复杂数据结构。因此,解决这些算法往往是从一开始就选择正确的数据结构。然后我回到了BitArray,即使二进制字符串非常大,这也给了我| OR的一些东西。感谢此链接和内容提供商:https://codereview.stackexchange.com/questions/80458/acm-icpc-team-challenge-on-hackerrank-easy

   static void Main(String[] args) {
    var input = Console.ReadLine().Split(' ').Select(item => int.Parse(item)).ToArray();
    var N = input[0];
    var M = input[1];
    var maxTopics = 0;
    var maxTeams = 0;
    var bitArray = new BitArray[N];

    for(var n = 0; n < N; n++){
        bitArray[n] = new BitArray(M);

        var topics = Console.ReadLine();

        for(var m = 0; m < M; m++){
            bitArray[n].Set(m, topics[m] == '1');
        }
    }

    for(int i = 0; i < N -1; i ++){
        for(int j = i + 1; j < N; j++){
            var tempTopics = BitsOnCount(new BitArray(M).Or(bitArray[i]).Or(bitArray[j]));

            if (tempTopics > maxTopics){
                maxTopics = tempTopics;
                maxTeams = 1;
            }else if(tempTopics == maxTopics){
                maxTeams++;
            }

        }
    }

    Console.WriteLine(maxTopics);
    Console.WriteLine(maxTeams);
}

static int BitsOnCount(BitArray bitArray)
{
    var count = 0;
    foreach (var bit in bitArray)
    {
        if ((bool) bit)
            count++;
    }

    return count;
}

4 个答案:

答案 0 :(得分:5)

只有操作数字,没有循环,LINQ等的解决方案应该是最佳性能。

var str1 = "10101";
var str2 = "11100";

var num1 = Convert.ToByte(str1, 2);
var num2 = Convert.ToByte(str2, 2);
var or = num1 | num2;

// We need to lookup only that bits, that are in original input values.
// So, create a mask with the same number of bits.
var mask = byte.MaxValue >> sizeof(byte) * 8 - Math.Max(str1.Length, str2.Length);
var result = (or & mask) == mask;

// True, when all bits after OR are 1, otherwise - False.
Console.WriteLine(result);

答案 1 :(得分:3)

如果要对两个等长的位数组执行二进制运算,可以使用Linq,

 var orResult = g[0].Zip(g[1], (b1, b2) => b1|b2).ToArray();

请注意,位操作传统上用于性能至关重要的情况。我不希望这个解决方案在批量操作中表现良好,但对于您的特定用例可能已经足够了。

<小时/> 如果您的用例是要发现任何结果位是否为&#39; 0&#39;,那么您可以使用linq&#39; All方法。一旦遇到零,它将停止并返回false。

 bool orResult = g[0].Zip(g[1], (b1, b2) => b1|b2).All(b => b != 0);

答案 2 :(得分:1)

对于较小的值(可以转换为整数),可以使用以下代码。它将二进制值转换为整数,然后应用或运算符|。然后将结果转换回二进制字符串。

using System;

public class Program
{
    public static void Main()
    {
        var str1 = "10101";
        var str2 = "11100";
        var mask = str1.Replace('0','1');
        int one = Convert.ToInt32(str1, 2);
        int two = Convert.ToInt32(str2, 2);
        int maskbit = Convert.ToInt32(mask, 2);
        int result = (one | two)^maskbit;

        if (result==0){

            Console.WriteLine("All flags set");             
        }
        else            
        {
            Console.WriteLine("Not all flags set");             
        }   
    }
}

答案 3 :(得分:0)

二进制OR运算符未在类型byte[]上定义,仅在byte上定义。

  

二进制|运算符是为整数类型和bool预定义的。对于整数类型,|计算其操作数的按位OR。对于bool操作数,|计算其操作数的逻辑OR;也就是说,当且仅当两个操作数均为假时,结果为false。

https://msdn.microsoft.com/en-us/library/kxszd0kx.aspx