将long转换为两个int以进行重构

时间:2011-06-02 19:51:14

标签: c# int

我需要将一个参数作为两个int参数传递给Telerik Report,因为它不能接受Long参数。什么是将长整数拆分为两个整数并在不丢失数据的情况下重建它的最简单方法?

6 个答案:

答案 0 :(得分:13)

使用遮蔽和移动是最好的选择。根据文档,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();
    }

注意整个按位操作的使用。这避免了在使用可能使用负数或舍入误差时可能发生的加法或其他数值运算时可能遇到的问题。

注意如果你能够使用无符号整数,你可以在上面的代码中用uint替换int(在这种情况下,这总是更好,因为它更清楚地发生了什么)。

答案 1 :(得分:6)

在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的原始字节并从字节中获取相应的整数。表示的转换不会发生太大变化。

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 :(得分:2)

        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));

答案 3 :(得分:2)

对于未签名,以下内容可行:

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

ulong value2 = ((ulong)high << 32) | low;

答案 4 :(得分:1)

将它转换为字符串和从字符串转换比将它转换成两个整数要简单得多。这是一个选择吗?

string myStringValue = myLongValue.ToString();

myLongValue = long.Parse(myStringValue);

答案 5 :(得分:1)

不要使用位操作,只需使用假联合即可。这也适用于不同的数据类型组合,而不仅仅是 long & 2 ints。更重要的是,当您真正只关心以一致的方式读取和写入位时,这避免了需要关注符号、字节顺序或其他低级细节。

using System;
using System.Runtime.InteropServices;

public class Program
{
    [StructLayout(LayoutKind.Explicit)]
    private struct Mapper
    {
        [FieldOffset(0)]
        public long Aggregated;
        [FieldOffset(0)]
        public int One;
        [FieldOffset(sizeof(int))]
        public int Two;
    }
    
    public static void Main()
    {
        var layout = new Mapper{ Aggregated = 0x00000000200000001 };
        var one = layout.One;
        var two = layout.Two;
        Console.WriteLine("One: {0}, Two: {1}", one, two);
        
        var secondLayout = new Mapper { One = one, Two = two };
        var aggregated = secondLayout.Aggregated;
        Console.WriteLine("Aggregated: {0}", aggregated.ToString("X"));
    }
}