Конвертировать long в два типа int с целью реконструкции - PullRequest
9 голосов
/ 02 июня 2011

Мне нужно передать параметр как два параметра int в отчет Telerik, так как он не может принимать длинные параметры. Какой самый простой способ разделить длинное на два целых и восстановить его без потери данных?

Ответы [ 5 ]

13 голосов
/ 03 июня 2011

Лучше всего использовать маскировку и смещение.long гарантированно будет 64-битным и int-32-битным, согласно документации, так что вы можете замаскировать биты на два целых числа и затем рекомбинировать.

См .:

    static int[] long2doubleInt(long a) {
        int a1 = (int)(a & uint.MaxValue);
        int a2 = (int)(a >> 32);
        return new int[] { a1, a2 };
    }

    static long doubleInt2long(int a1, int a2)
    {
        long b = a2;
        b = b << 32;
        b = b | (uint)a1;
        return b;
    }


    static void Main(string[] args)
    {
        long a = 12345678910111213;
        int[] al = long2doubleInt(a);
        long ap = doubleInt2long(al[0],al[1]);
        System.Console.WriteLine(ap);
        System.Console.ReadKey();
    }

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

Обратите внимание, что вы можете заменить int на uint в приведенном выше коде, если вы можете использовать целые числа без знака (это всегда предпочтительнее в такой ситуации, так как намного яснее, что происходит с битами).

6 голосов
/ 03 июня 2011

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

const long LOW_MASK = ((1L << 32) - 1);
long value = unchecked((long)0xDEADBEEFFEEDDEAD);
int valueHigh = (int)(value >> 32);
int valueLow  = (int)(value & LOW_MASK);
long reconstructed = unchecked((long)(((ulong)valueHigh << 32) | (uint)valueLow));

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

long value = unchecked((long)0xDEADBEEFFEEDDEAD);
byte[] valueBytes = BitConverter.GetBytes(value);
int valueHigh = BitConverter.ToInt32(valueBytes, BitConverter.IsLittleEndian ? 4 : 0);
int valueLow  = BitConverter.ToInt32(valueBytes, BitConverter.IsLittleEndian ? 0 : 4);
byte[] reconstructedBytes = BitConverter.IsLittleEndian
    ? BitConverter.GetBytes(valueLow).Concat(BitConverter.GetBytes(valueHigh)).ToArray()
    : BitConverter.GetBytes(valueHigh).Concat(BitConverter.GetBytes(valueLow)).ToArray();
long reconstructed = BitConverter.ToInt64(reconstructedBytes, 0);
2 голосов
/ 03 июня 2011

Для неподписанных будет работать следующее:

ulong value = ulong.MaxValue - 12;
uint low = (uint)(value & (ulong)uint.MaxValue);
uint high = (uint)(value >> 32);

ulong value2 = ((ulong)high << 32) | low;
2 голосов
/ 03 июня 2011
        long x = long.MaxValue;
        int lo = (int)(x & 0xffffffff);
        int hi = (int)((x - ((long)lo & 0xffffffff)) >> 32);
        long y = ((long)hi << 32) | ((long)lo & 0xffffffff);

        Console.WriteLine(System.Convert.ToString(x, 16));
        Console.WriteLine(System.Convert.ToString(lo, 16));
        Console.WriteLine(System.Convert.ToString(hi, 16));
        Console.WriteLine(System.Convert.ToString(y, 16));
1 голос
/ 03 июня 2011

Преобразование в строку и из нее будет намного проще, чем преобразование двух и пары целых чисел.Это опция?

string myStringValue = myLongValue.ToString();

myLongValue = long.Parse(myStringValue);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...