简体   繁体   English

在C#中对两个整数进行异或的最快方法是什么?

[英]What is the fastest way to XOR two integers in C#?

I need to XOR one integer a against array of integers q (max of 100,000). 我需要对一个整数q (最大值为100,000)的数组求一个整数a ie if i am looping, I will 即如果我正在循环,我会

a XOR q[0] 异或q [0]

a XOR q[1] 异或[1]

..... .....

a XOR q[100000] 异或q [100000]

(100,000 times) (100,000次)

I will have a series of such a to be XORed. 我将有一系列这样a待对照。

I am writing a console application which will be pass the required input. 我正在编写一个控制台应用程序,它将传递所需的输入。

I am using the built-in C# ^ operator to do the XOR operation. 我使用内置的C# ^运算符来执行XOR运算。 Is there any other way? 还有其他方法吗?

Would converting the integer to a byte array and then XORing each bit and figuring out the end result be a good idea? 将整数转换为字节数组然后对每个位进行异或并找出最终结果是一个好主意吗?

Input (don't keep the spaces between the two lines) 输入(不要保持两行之间的空格)

1 1

15 8 15 8

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

10 6 10 10 6 10

1023 7 7 1023 7 7

33 5 8 33 5 8

182 5 10 182 5 10

181 1 13 181 1 13

5 10 15 5 10 15

99 8 9 99 8 9

33 10 14 33 10 14

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace XOR
{
    class Solution
    {
        static void Main(string[] args)
        {

            List<TestCase> testCases = ReadLine();
            //Console.WriteLine(DateTime.Now.ToLongTimeString());
            CalculationManager calculationManager = new CalculationManager();

            foreach (var testCase in testCases)
            {
                var ints = testCase.Queries.AsParallel().Select(query => calculationManager.Calculate(query, testCase.SequenceOfIntegers)).ToList();
                ints.ForEach(Console.WriteLine);
            }

            //Console.WriteLine(DateTime.Now.ToLongTimeString());
            //Console.ReadLine();
        }

        private static List<TestCase> ReadLine()
        {
            int noOfTestCases = Convert.ToInt32(Console.ReadLine());
            var testCases = new List<TestCase>();

            for (int i = 0; i < noOfTestCases; i++)
            {
                string firstLine = Console.ReadLine();
                string[] firstLineSplit = firstLine.Split(' ');
                int N = Convert.ToInt32(firstLineSplit[0]);
                int Q = Convert.ToInt32(firstLineSplit[1]);

                var testCase = new TestCase
                                   {
                                       Queries = new List<Query>(),
                                       SequenceOfIntegers = ReadLineAndGetSequenceOfIntegers()
                                   };

                for (int j = 0; j < Q; j++)
                {
                    var buildQuery = ReadLineAndBuildQuery();
                    testCase.Queries.Add(buildQuery);
                }

                testCases.Add(testCase);
            }

            return testCases;
        }

        private static List<int> ReadLineAndGetSequenceOfIntegers()
        {
            string secondLine = Console.ReadLine();
            List<int> sequenceOfIntegers = secondLine.Split(' ').ToArray().Select(x => Convert.ToInt32(x)).ToList();
            return sequenceOfIntegers;
        }

        private static Query ReadLineAndBuildQuery()
        {
            var query = Console.ReadLine();
            List<int> queryIntegers = query.Split(' ').ToArray().Select(x => Convert.ToInt32(x)).ToList();
            Query buildQuery = ReadLineAndBuildQuery(queryIntegers[0], queryIntegers[1], queryIntegers[2]);
            return buildQuery;
        }

        private static Query ReadLineAndBuildQuery(int a, int p, int q)
        {
            return new Query { a = a, p = p, q = q };
        }


    }

    class CalculationManager
    {
        public int Calculate(Query query, List<int> sequenceOfIntegers)
        {
            var possibleIntegersToCalculate = FindPossibleIntegersToCalculate(sequenceOfIntegers, query.p, query.q);
            int maxXorValue = possibleIntegersToCalculate.AsParallel().Max(x => x ^ query.a);
            return maxXorValue;
        }

        private IEnumerable<int> FindPossibleIntegersToCalculate(List<int> sequenceOfIntegers, int p, int q)
        {
            return sequenceOfIntegers.GetRange(p - 1, (q - p) + 1).Distinct().ToArray();
        }
    }

    class TestCase
    {
        public List<int> SequenceOfIntegers { get; set; }
        public List<Query> Queries { get; set; }
    }

    class Query
    {
        public int a { get; set; }
        public int p { get; set; }
        public int q { get; set; }
    }
}

Using the ^ bit-wise xor operator is the fastest way to xor integers. 使用^ bit-wise xor运算符是xor整数的最快方法。

The operation is translated to a single atomic processor operation. 该操作被转换为单个原子处理器操作。

As you can see in the disassembly: 正如你在反汇编中看到的那样:

        int i = 4;
00000029  mov         dword ptr [ebp-3Ch],4 
        i ^= 3;
00000030  xor         dword ptr [ebp-3Ch],3 

So if you wish to make your code run faster, you should change the algorithm / approach (as suggested by Marc Gravell), not the xor method. 因此,如果您希望使代码运行得更快,则应更改算法/方法(如Marc Gravell所建议),而不是xor方法。

The only thing I'd even try (if there was reason to think the int approach was too slow) would be to use unsafe code to treat each int[] as a long* , and use 64-bit arithmetic (again, using ^ ) instead of 32, half the iterations, and a bit less indirection. 我甚至尝试过的唯一一件事(如果有理由认为int方法太慢)将使用unsafe代码将每个int[]视为long* ,并使用64位算法(再次使用^而不是32,迭代的一半,以及更少的间接。 IIRC that is pretty much what I did for some web-socket code (applying web-socket masks for client-to-server messages is a bulk XOR). IIRC就像我为一些Web套接字代码所做的那样(为客户端到服务器消息应用Web套接字掩码是一个批量异或)。 You'd need to be careful for the last few bytes, obviously. 显然,你需要小心最后几个字节。

If you have to xor more elements called a (as you said) against the array you can speed this up the following way: 如果你需要对阵列中的更多元素(如你所说),你可以通过以下方式加快速度:

int x = q[0]
for(int i = 1; i < q.Length; i++)
   x ^= q[i]

a1 ^= x
a2 ^= x
...

EDIT: Sorry, than basically the other way around 编辑:对不起,基本上相反

int x = a1 ^ a2 ^ ... an
for(int i = 0; i < q.Length; i++)
     q[i] ^= x

XOR is a fast operation so your application will be limited by the rate you can generate the integers. XOR是一种快速操作,因此您的应用程序将受到生成整数的速率的限制。

If you just xor them as they become available the xor time will be neglectable regardless of method. 如果你只是在它们变得可用的时候对它们进行xor,那么无论方法如何,xor时间都可以忽略不计。

eg if you read the integers from a text file. 例如,如果您从文本文件中读取整数。 The disk io + parse time will be several magnitudes bigger than the xor time. 磁盘io +解析时间将比xor时间大几个数量级。 The operating system will also use read-ahead which in practice means that it fetches the next batch of integers while you process the current batch. 操作系统还将使用read-ahead这实际上意味着它在处理当前批处理时获取下一批整数。 This means that parsing + xor adds no extra time to the overall processing time except for the last batch. 这意味着解析+ xor不会为整个处理时间增加额外的时间,除了最后一批。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM