2011-06-02 13 views
8

Uzun parametreler kabul edemediğinden bir parametreyi bir Telerik Raporuna iki int parametresi olarak aktarmam gerekiyor. Uzun iki bölüme ayırmanın ve verileri kaybetmeden yeniden yapılandırmanın en kolay yolu nedir?Yeniden yapılandırma amacıyla uzun bir iki int dönüştürme

+3

Bayt dizisine dönüştürme ve bir tanesini highBits olarak gönder, diğerini lowBits olarak gönder? Ayrıca, kediniz oldukça tatlı görünüyor ve tamamen kedim ile parti olur. – Yuck

+1

Şüphesiz iki ints uzun demek? – MGwynne

+1

Numaralar imzalanacak mı yoksa imzasız mı olacak? –

cevap

11

Maskelemeyi ve kaydırmayı kullanmak en iyi seçimdir. belgelere göre, 64 bit ve int 32 bit uzunluğunda olduğu garanti edilir, böylece bitleri iki tam sayıya ayırabilir ve sonra yeniden birleştirebilirsiniz.

Bkz:

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

Not boyunca bitsel operasyonları kullanımı. Bu, negatif sayılar veya yuvarlama hataları kullanılarak meydana gelebilecek toplama veya diğer sayısal işlemleri kullanırken birinin alabileceği sorunları önler.

İmzasız tamsayılar kullanabiliyorsanız, yukarıdaki koddaki int ile uint'i değiştirebileceğinizi unutmayın (bu durum her zaman bu tür durumlarda tercih edilir, çünkü bitlerle olan bitenden daha nettir).

+1

Sol tam sayıdaki negatif sayıları desteklemek için "long2doubleInt" ve "doubleInt2long" işlevlerini "unchecked" ile işaretlemem gerekiyor. –

1
long spork = 0x7f1234567f125953; 
int[] ints = new int[2]; 
ints[0] = (int)(spork >> 32); 
ints[1] = (int)(spork & (long)0xFFFFFFFF); 

long reconstructed = ((long)ints[0] << 32) + (long)ints[1]; 

Bu iş sizin için mi?

+0

Bu yöntem işe yaramazsa, 'spork' çok büyük bir sayıysa ('long.MaxValue' yakınında) –

+0

Burada eklemeyi kullanmamalısınız. Uzun spork = -1; Daha sonra yeniden inşa edilen verimler -4294967297. – MGwynne

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

unigned için aşağıdaki çalışır: ve bir dize onu dönüştürme

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

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

o ikisini ve ints bir çift dönüştürme çok daha basit olurdu. Bu bir seçenek mi?

string myStringValue = myLongValue.ToString(); 

myLongValue = long.Parse(myStringValue); 
3

C# içinde bit-manipülasyon yapmak, özellikle imzalı değerler ile uğraşırken bazen zor olabilir. Bit manipülasyonu yapmayı planladığınızda imzasız değerler kullanmanız gerekir. Ne yazık ki en güzel görünen kodu vermeyecek.

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

bunu yapmak için güzel bir yol istiyorsanız, uzun süre çiğ bayt almak ve bayt karşılık gelen tamsayılar olsun. Temsiller arası/dönüşümü çok değişmez.

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); 
İlgili konular