Объединить два Int32 в Int64 - PullRequest
3 голосов
/ 01 апреля 2012

Имейте словарь , который часто используется. Я имею в виду цикл, который работает в течение нескольких дней при большой загрузке данных. Int64 приходит из двух Int32. Байт - это расстояние (количество) между этими двумя Int32 из многих очень длинных списков.

В этом цикле мне нужно сделать

  • Генерация ключа
  • Если ключ не существует в словаре, введите ключ и значение
  • Если ключ существует, и новое значение (байт) меньше существующего значения, тогда замените существующее значение новым значением

Сейчас я использую прямую математику для генерации ключа, и я знаю, что есть более быстрый путь, но я не могу понять это. Я поставил shift как тег, так как думаю, что это то, как его оптимизировать, но я не могу понять это.

Затем, когда цикл завершится, мне нужно извлечь два Int32 из Int64, чтобы вставить данные в базу данных.

Спасибо

За комментарий, который я использую, чтобы объединить два Int32 в один Int64

        Int64 BigInt;
        Debug.WriteLine(Int32.MaxValue);
        Int32 IntA = 0;
        Int32 IntB = 1;
        BigInt = ((Int64)IntA * Int32.MaxValue) + IntB;
        Debug.WriteLine(BigInt.ToString());
        IntA = 1;
        IntB = 0;
        BigInt = ((Int64)IntA * Int32.MaxValue) + IntB;
        Debug.WriteLine(BigInt.ToString());
        IntA = 1;
        IntB = 1;
        BigInt = ((Int64)IntA * Int32.MaxValue) + IntB;
        Debug.WriteLine(BigInt.ToString());

И лучшим ключом может быть не Int64. У меня есть два Int32, которые вместе образуют ключ. И значение байта. Мне нужен быстрый поиск этого составного ключа. Словарь работает быстро, но не поддерживает составной ключ, поэтому я создаю один ключ, который на самом деле является составным ключом. В SQL Int32A Int32B образуют PK.

Причина, по которой я не использую составной ключ, заключается в том, что мне нужна скорость поиска в словаре, и, насколько мне известно, словарь не поддерживает составной ключ. Это производственный код. В таблице SQL фактически есть третий ключ (Int32 sID, Int32 IntA, Int32 IntB). В этом парсере я имею дело только с одним sID одновременно (и sID обрабатываются по порядку). Я начал с поиска составного ключа в SQL (миллиарды за раз). Когда я вытащил IntA, IntB из словаря для обработки одного sID, а затем загрузил в SQL по завершении каждого sID, я получил улучшение производительности на 100: 1. Часть улучшения производительности - вставка, так как когда я вставляю из словаря, я могу вставлять в порядке PK. Новые IntA и IntB не производятся отсортированными при разборе, поэтому прямая вставка в SQL может серьезно фрагментировать индекс, и мне нужно будет перестроить индекс в конце прогона.

Ответы [ 3 ]

11 голосов
/ 01 апреля 2012

Если вы хотите конвертировать туда и обратно из Int32 в Int64, вы можете использовать структуру с явным макетом:

//using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Explicit)]
struct Int64ToInt32
{
    [FieldOffset(0)]
    public Int64 Int64Value;
    [FieldOffset(0)]
    public Int32 LeftInt32;
    [FieldOffset(4)]
    public Int32 RightInt32;
}

Просто установите / получите значения из полей.

8 голосов
/ 01 апреля 2012

Звучит так, будто ты просто хочешь смену.Лично мне проще думать о сдвиге битов при использовании типов без знака вместо знаков со знаком:

// Note: if you're in a checked context by default, you'll want to make this
// explicitly unchecked
uint u1 = (uint) int1;
uint u2 = (uint) int2;

ulong unsignedKey = (((ulong) u1) << 32) | u2;
long key = (long) unsignedKey;

И наоборот:

ulong unsignedKey = (long) key;
uint lowBits = (uint) (unsignedKey & 0xffffffffUL);
uint highBits = (uint) (unsignedKey >> 32);
int i1 = (int) highBits;
int i2 = (int) lowBits;

Вполне возможно, что вам не нужны всеэти преобразования в беззнаковые типы.Это больше для моего здравого смысла, чем что-либо еще:)

Обратите внимание, что вам нужно привести u1 к ulong, чтобы смещение работало в нужном месте - смещение uint на 32 битаНичего.

Обратите внимание, что это способ объединения двух 32-целых чисел для получения 64-разрядного целого числа.Это не просто только в любом случае.

(Примечание: решение Баса работает отлично - мне просто не всегда нравится такой подход, без какой-либо конкретной причины).)

1 голос
/ 01 апреля 2012

Вы можете использовать сдвиг битов для хранения двух 32-битных значений в одной 64-битной переменной.

Я приведу небольшой пример:

int a = 10;
int b = 5;
long c;

//To pack the two values in one variable
c = (long)a << 32;
c = c + (long)b;
//the 32 most significant bits now contain a, the 32 least significant bits contain b

//To retrieve the two values:
c >> 32 == a
c - ((c>>32)<<32) == b

Правка: я вижу, что я немного опоздална вечеринку, просто хотел проверить в VS, если я не ошибся:)

...