Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a long to two int for the purpose of reconstruction

Tags:

c#

int

I need to pass a parameter as two int parameters to a Telerik Report since it cannot accept Long parameters. What is the easiest way to split a long into two ints and reconstruct it without losing data?

like image 699
Keith Adler Avatar asked Jun 02 '11 19:06

Keith Adler


2 Answers

Using masking and shifting is your best bet. long is guaranteed to be 64 bit and int 32 bit, according to the documentation, so you can mask off the bits into the two integers and then recombine.

See:

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

Note the use of bitwise operations throughout. This avoids the problems one might get when using addition or other numerical operations that might occur using negative numbers or rounding errors.

Note you can replace int with uint in the above code if you are able to use unsigned integers (this is always preferable in this sort of situation, as it's a lot clearer what's going on with the bits).

like image 143
MGwynne Avatar answered Oct 31 '22 09:10

MGwynne


Instead of mucking with bit operations, just use a faux union. This also would work for different combinations of data types, not just long & 2 ints. More importantly, that avoids the need to be concerned about signs, endianness or other low-level details when you really only care about reading & writing bits in a consistent manner.

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"));
    }
}
like image 32
this Avatar answered Oct 31 '22 09:10

this