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

本文关键字:int 两个 重建 转换 long | 更新日期: 2023-09-27 17:58:21

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

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

使用掩码和移位是最好的选择。根据文档,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(在这种情况下,这总是更可取的,因为它更清楚地显示了比特的情况)。

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

对于unigned,以下内容将起作用:

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

与其处理位操作,不如使用伪并集。这也适用于数据类型的不同组合,而不仅仅是长&2分。更重要的是,当你真的只关心阅读&以一致的方式写入位。

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

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

string myStringValue = myLongValue.ToString();
myLongValue = long.Parse(myStringValue);