Advertisement
caufman

BitShift

Jun 19th, 2019
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. Attribute VB_Name = "BitShift"
  2.  
  3. 'Функция осуществляет побитовый сдвиг целого числа number в сторону старших разрядов на количество,
  4. 'равное bitCount (в случае отрицательного bitCount - сдвиг в сторону младших разрядов).
  5. Function Shift(ByVal number As Variant, ByVal bitCount As Long) As Variant
  6.     Dim i As Long, size As Long, mask As Variant, mask_ As Variant, vtype As VbVarType
  7.     Dim tolow As Boolean, signed As Boolean, signchange As Boolean
  8.     vtype = VarType(number)
  9.     Select Case vtype
  10.         Case vbByte
  11.             size = 8
  12.             signed = False
  13.         Case vbInteger
  14.             size = 16
  15.             signed = True
  16.         Case vbLong
  17.             size = 32
  18.             signed = True
  19.         Case vbCurrency
  20.             size = 64
  21.             signed = True
  22.         Case Else
  23.             Err.Raise 5, "Shift", "Аргумент number должен быть целочисленным (типа Byte, Integer, Long или Currency)."
  24.     End Select
  25.     If bitCount = 0 Then
  26.         Shift = number
  27.         Exit Function
  28.     ElseIf bitCount < 0 Then
  29.         bitCount = -bitCount
  30.         tolow = True
  31.     End If
  32.     If bitCount < size Then
  33.         Select Case True
  34.             Case Not tolow And Not signed
  35.                 mask = 1
  36.                 For i = 1 To size - 1
  37.                     mask = mask * 2
  38.                 Next i
  39.                 mask = mask - 1
  40.                 For i = 1 To bitCount
  41.                     number = (number And mask) * 2
  42.                 Next i
  43.             Case Not tolow And signed
  44.                 If vtype = vbCurrency Then
  45.                     mask_ = 0.0001@
  46.                     mask = -mask_
  47.                 Else
  48.                     mask = -1
  49.                     mask_ = 1
  50.                 End If
  51.                 For i = 1 To size - 2
  52.                     mask = mask * 2
  53.                     mask_ = mask_ * 2
  54.                 Next i
  55.                 mask = mask * 2
  56.                 For i = 1 To bitCount
  57.                     number = number And Not mask 'Обнуляем знаковый разряд.
  58.                    If (number And mask_) = mask_ Then 'Если есть бит перед знаковым разрядом...
  59.                        number = number And Not mask_ '...то убираем его.
  60.                        signchange = True
  61.                     End If
  62.                     number = number * 2 'Осуществляем сдвиг в сторону старших разрядов.
  63.                    If signchange Then  'Если был убран бит перед знаковым разрядом...
  64.                        number = number Or mask   '...то вставляем его в знаковый разряд.
  65.                        signchange = False
  66.                     End If
  67.                 Next i
  68.             Case tolow And Not signed
  69.                 For i = 1 To bitCount
  70.                     number = number \ 2
  71.                 Next i
  72.             Case tolow And signed
  73.                 If vtype = vbCurrency Then
  74.                     mask_ = CCur(1) / CCur(10000)
  75.                     mask = -mask_
  76.                 Else
  77.                     mask = -1
  78.                     mask_ = 1
  79.                 End If
  80.                 For i = 1 To size - 2
  81.                     mask = mask * 2
  82.                     mask_ = mask_ * 2
  83.                 Next i
  84.                 mask = mask * 2
  85.                 For i = 1 To bitCount
  86.                     If (number And mask) = mask Then 'Если есть бит в знаковом разряде...
  87.                        number = number And Not mask '...то обнуляем знаковый разряд.
  88.                        signchange = True
  89.                     End If
  90.                     number = number \ 2 'Осуществляем сдвиг в сторону младших разрядов.
  91.                    If signchange Then  'Если был убран бит из знакового разряда...
  92.                        number = number Or mask_  '...то вставляем его в бит перед знаковым разрядом.
  93.                        signchange = False
  94.                     End If
  95.                 Next i
  96.         End Select
  97.         Shift = number
  98.     Else
  99.         Select Case vtype
  100.             Case vbByte
  101.                 Shift = CByte(0)
  102.             Case vbInteger
  103.                 Shift = 0
  104.             Case vbLong
  105.                 Shift = 0&
  106.             Case vbCurrency
  107.                 Shift = 0@
  108.         End Select
  109.     End If
  110. End Function
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement