パソコン活用研究5番街(Visual Basic、Excel(VBA)、BASIC プログラミング研究)


シフト演算とビット演算
(準備中)

VB.Netのシフト演算

左シフト <<
右シフト >>

変数xを左に1ビットシフトするときは、 x = x <<1 と書く。
右に1ビットシフトするときは、x = x>>1

左シフトでは最下位ビットに常に0が補なわれる。
例えば、00000101(10進数の5)を1ビット左シフトすると、00001010(10進数の10)になる。

右シフト演算の場合、左オペランド(シフトされる値)が符号付整数の場合は算術シフト(負数の場合は
最上位ビットに1、正数の場合は0が補われる)
符号なし正数の場合は、論理シフト(最上位ビットには0が補われる)になる。

例えば符号付正数、00001010(10進数の10)を1ビット右シフトすると00000101(10進数の5)になる。

シフト演算はある意味、2進法におけるケタ上り(10進法の2倍)、ケタ下がり(10進法の1/2倍)なので
シフト演算をうまく使うと、掛け算に活用できます。


VB.Netのビット演算

論理否定 Not
論理積 And
論理和 Or
排他的論理和 Xor

C言語での説明ですが、シフト演算、ビット演算については、「Cの演算子」もご参照下さい。


コンピュータの内部では数値は2進法で表現されているので、
シフト演算をうまく使うと、乗算の記号*を使わずに掛け算することができます。


入力された値の、2倍、4倍、5倍、10倍、16倍をシフト演算で計算するプログラム。


実行画面



tobinary()という関数は10進数を2進数(の文字列)に変換しています。


Imports System

Module Program
Sub Main(args As String())
Dim x, x2, x4, x5, x8, x10, x16 As Integer

x = Console.ReadLine()
x2 = x << 1
x4 = x << 2
x5 = (x << 2) + x
x8 = x << 3
x10 = (x << 3) + (x << 1)
x16 = x << 4

Console.WriteLine("2倍:{0} : {1}", x2, tobinary(x2))
Console.WriteLine("4倍:{0} : {1}", x4, tobinary(x4))
Console.WriteLine("5倍:{0} : {1}", x5, tobinary(x5))
Console.WriteLine("8倍:{0} : {1}", x8, tobinary(x8))
Console.WriteLine("10倍:{0} : {1}", x10, tobinary(x10))
Console.WriteLine("16倍:{0} : {1}", x16, tobinary(x16))

End Sub

Function tobinary(n As Integer) As String
Return Convert.ToString(n, 2)
End Function

End Module





ビット演算子も使うと、掛け算の計算をすることができます。

シフト演算、ビット演算のみで掛け算を行うプログラム

実行例



x = 5
y = 6
とすると、x * 6は
2進数で書くと
00000101 * 00000110 と書けます。

x   00000101
y    00000110
--------------
    00000000
    00000101
   00000101

これは、yの最下位ビットから1ビットづつ、0か1か判定し、
1だったら、yの当該ケタ数分だけxを左シフトし、その値を順次足していく
という作業です。

なので、以下のようにコーディングすることで実装できます。
yのほうは順次右シフトし、y And 1 で最下位ビットのみ0か1か判定しています。

乗算命令をもっていないCPUなんかの場合、乗算を機械語でコーディングするときは
こんなアルゴリズムを使うこともあったような気がします。(8ビットCPU以前の時代)



For i = 0 To Len(str) - 1
If (y And 1) = 1 Then t(i) = x << i Else t(i) = 0
result = result + t(i)
y = y >> 1
Next


Imports System

Module Program
Sub Main(args As String())
Dim x, y, t(10), result As Integer
Dim str As String
Console.Write("ひとつめの数:")
x = Console.ReadLine()
Console.Write("ふたつめの数:")
y = Console.ReadLine()
Console.WriteLine("{0} * {1} =>2進数 {2} * {3}", x, y, tobinary(x), tobinary(y))
str = tobinary(y)
For i = 0 To Len(str) - 1
If (y And 1) = 1 Then t(i) = x << i Else t(i) = 0
result = result + t(i)
y = y >> 1

Next

Console.WriteLine("結果:{0} :2進数 {1}", result, tobinary(result))


End Sub



Function tobinary(n As Integer) As String
Return Convert.ToString(n, 2)
End Function
End Module


Convert.Tostring()では小数を含むと変換できないようなので、
ついでに、10進数の小数を2進数に変換して表示するプログラムを載せておきます。
ただし2進法の小数部は8ケタなので、対応する入力値は10進法の0.01〜0.99くらい。



やってることは、・・
入力された小数を256倍する。(つまり8ビット分の左シフトと同じ)
小数部を切り捨てして整数部だけ取り出す。
2進数に変換
2進数の小数として表示



Imports System

Module Program
Sub Main(args As String())
Dim s As String
Dim f As Single
Dim b(7), fract As Integer

s = Console.ReadLine()
f = Int(Single.Parse(s) * 256)
fract = 0
For i = 0 To 7
If fract = 1 Then b(i) = 0 : Continue For
b(i) = f Mod 2
f = (f - b(i)) / 2
If f < 1 Then fract = 1
Next

Console.Write("0.")
For i = 7 To 0 Step -1
Console.Write(b(i).ToString())
Next
End Sub
End Module






TopPage > Visual BasIc&Excel活用研究目次