Я хочу знать конкретную причину, по которой мы взяли эти 256, .. чисел в приведенном ниже преобразовании - PullRequest
0 голосов
/ 09 октября 2019

Прогнозируемый код используется для преобразования даты в целое число и наоборот. Я хочу знать причину, по которой здесь мы использовали этот конкретный шестнадцатеричный код и числовой ряд, чтобы получить дату от intЕсли есть статья об этом примере кода, это также поможет мне понять этот код на самом деле.

Я пробовал онлайн преобразование шестнадцатеричного числа в десятичное для этого кода и нашел его 256 ^ 1,256 ^ 2 ... даже еслипытаясь не найти точную причину.

declare @dDate date = '2017-10-12'
declare @iDate int = 0

select @iDate = ( (datepart(year,@dDate)*65536 | datepart(month,@dDate)*256 | datepart(dd,@dDate)))

select (@iDate&0xfff0000)/65536  --year
select (@iDate&0xff00)/256   --Month
select (@iDate&0xff)         --Date

Ответы [ 2 ]

1 голос
/ 09 октября 2019

& - оператор, выполняющий побитовое И"|"побитовый ИЛИ. См. здесь и здесь . Также см. здесь для объяснения использования побитового И / ИЛИ для хранения нескольких числовых значений в одном числовом столбце. Эта часть:

@iDate&0xfff0000

будет «маскировать» или исключать / заменять нулями ту часть iDate, которая отличается от 256 ^ 2. Затем вы делите на 65536 - что просто меняет исходную математику умножения года на 65536.

Если концепция побитового И чужеродна, я приведу пример, который НЕ РАБОТАЕТ в десятичном виде. Битовое И преобразует все это в двоичное, а затем маскирует вещи (например, подсеть IP, если вы знакомы с этим).

В любом случае, рассмотрите десятичное число 20171012. Если такое понятие как десятичное Исуществует, это может выглядеть как 20171012&11110000. Места "1" - это "хранители", а места "0" - "выбрасывание". Если вы сложите их вертикально, результатом будет сохранение значений с «1» под ними и замена значений с «0» под ними на «0».

number       20171012
dec-wise AND 11110000
result       20170000

теперь результат равенЭто не 2017 год, поэтому вам придется разделить на 10000, чтобы получить 2017 год. Для 20171012&1100 вы должны использовать подразумеваемые лидирующие нули:

number       20171012
dec-wise AND 00001100
result           1000

Я, вероятно, преобразовал бы в int, добавив год *10000 и месяц * 100 и день. Возвращаясь назад, я бы использовал комбинацию целочисленного деления и MOD. Но я думаю, что побитовое И, возможно, немного более элегантно (особенно для получения месяца).

На основе вашего комментария я расскажу, как я конвертировал даты в int и возвращал обратно:

declare @dDate date = '2017-10-12'
declare @iDate int

set @iDate = year(@dDate) * 10000 + month(@dDate) * 100 + day(@dDate)

select @iDate

select 'year', @iDate/10000 -- basic integer division provides the year
select 'month', (@iDate % 10000)/100 -- combine modulo and integer division to get the month
select 'day', @iDate % 100  -- basic modulo arithmetic provides the day

возвращает:

20171012
year    2017
month     10
day       12
0 голосов
/ 09 октября 2019

Это битовая манипуляция.

Сдвиг битов

Десятичная дробь 3 = двоичная 11

Если мы делаем сдвиг влево (<<)4 bits в 3 он станет 48, что равно двоичному 110000 <- <code>4 добавлено ноль битов из-за сдвига влево

Но так как у нас нет операторов сдвига битовT-SQL, следовательно, мы можем сделать математику.

Сдвиг влево n битов в числе x = x * 2^n

Следовательно, кратное число с 256 фактически сдвиг влево 8биты из этого числа (2 ^ 8 = 256).

Позже, когда вы делаете поразрядное OR между двумя числами, они фактически "объединяют" биты вверх.

Например, вам нужночтобы объединить 2 двоичных числа, (3) 11 и (2) 10, результирующее число должно быть 1110 = 14

Итак, сначала мы сделаем 2 сдвига влево в 3 = 3 * 2 ^ 2 = 12 итогда мы сделаем побитовое OR это число со следующим числом

    12 = 1100
     2 = 0010
OR 
---------------
    14 = 1110

Ваш пример фактически сохраняет всю дату в целочисленной переменной, которая являетсяОчень эффективный способ сохранения даты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...