ゆるゆるプログラミング

・2倍と左ビットシフトの速度

ここでは、int型変数の掛け算による2倍、左ビットシフトによる2倍の2種類の計算を、それぞれ1000万回行い、処理開始から終了するまでの時間をナノ秒単位で計測しました。

また、この処理を9回繰り返し行いました。

ここから、Javaのソースコードを使って解説していきます。

TimeBitshiftL1.java ← クリックしてダウンロードページに移動
001:    public class TimeBitshiftL1 {
002:    	public static void main( String[] args ) {
003:    		int  number;
004:    		int  x;
005:    		long ts, te, tresult1, tresult2;
006:    
007:    		// 9回計測
008:    		for ( number = 1; number <= 9; ++ number ) {
009:    			// 2倍
010:    			ts = System.nanoTime();
011:    			x = 0;
012:    			for ( int i = 1; i <= 10000000; ++ i ) {
013:    				x = x * 2;
014:    			}
015:    			te = System.nanoTime();
016:    			tresult1 = te - ts;
017:    
018:    			// ビットの左シフト
019:    			ts = System.nanoTime();
020:    			x = 0;
021:    			for ( int i = 1; i <= 10000000; ++ i ) {
022:    				x = x << 1;
023:    			}
024:    			te = System.nanoTime();
025:    			tresult2 = te - ts;
026:    
027:    			// 結果表示
028:    			System.out.println( number + "回目  2倍:" + tresult1
029:    					 + "ナノ秒  左シフト:" + tresult2
030:    					 + "ナノ秒   "
031:    					 + (double)tresult2 / (double)tresult1 );
032:    		}	
033:    	}
034:    }

TimeBitshiftL1.Javaの出力結果

1回目  2倍:4520189ナノ秒  左シフト:3852210ナノ秒   0.8522232145602762
2回目  2倍:3995899ナノ秒  左シフト:3803886ナノ秒   0.9519474841581331
3回目  2倍:3817571ナノ秒  左シフト:3803886ナノ秒   0.9964152598602619
4回目  2倍:3856914ナノ秒  左シフト:3831255ナノ秒   0.993347271938135
5回目  2倍:3813294ナノ秒  左シフト:3782931ナノ秒   0.9920375926954491
6回目  2倍:4112645ナノ秒  左シフト:4225970ナノ秒   1.0275552594498187
7回目  2倍:4683549ナノ秒  左シフト:4179357ナノ秒   0.8923483025372426
8回目  2倍:4179784ナノ秒  左シフト:3947575ナノ秒   0.9444447368572156
9回目  2倍:3959548ナノ秒  左シフト:3805597ナノ秒   0.9611190469215173

結果の1番右の数値は、左シフトの処理時間を2倍の処理時間で割ったものです。

この値が0.0未満の場合、2倍の処理時間が左シフトの処理時間より長かったことを意味してします。1.0より大きい場合、2倍の処理時間が左シフトの処理時間より短かったことを意味してします。

この結果から、2倍の処理時間が左シフトの処理時間より少しだけ長くなりそうなことがわかります。6回目の結果は、左シフトの処理時間のほうが長かったことを示しているので、左シフトの処理時間が必ずしも短いとはいえません。

ここから、ソースコードの主要部分について解説してきます。

009:    			// 2倍
010:    			ts = System.nanoTime();
011:    			x = 0;
012:    			for ( int i = 1; i <= 10000000; ++ i ) {
013:    				x = x * 2;
014:    			}
015:    			te = System.nanoTime();
016:    			tresult1 = te - ts;

int型変数xに0を代入して、その変数xに対して2倍する処理を1000万回行っています。処理終了時間tsと処理開始時間tsの差を処理時間tsresult1に代入しています。

018:    			// ビットの左シフト
019:    			ts = System.nanoTime();
020:    			x = 0;
021:    			for ( int i = 1; i <= 10000000; ++ i ) {
022:    				x = x << 1;
023:    			}
024:    			te = System.nanoTime();
025:    			tresult2 = te - ts;

int型変数xに0を代入して、その変数xに対して1回の左ビットシフトを1000万回行っています。処理終了時間tsと処理開始時間tsの差を処理時間tsresult2に代入しています。

次に、"TimeBitshiftL1.Java"の2倍する値と左シフトする回数をint型変数に変更したソースコードで処理時間の比較を行いました。

TimeBitshiftL2.java ← クリックしてダウンロードページに移動
001:    public class TimeBitshiftL2 {
002:    	public static void main( String[] args ) {
003:    		int  number;
004:    		int  x;
005:    		int  mulnum, shiftnum;
006:    		long ts, te, tresult1, tresult2;
007:    
008:    		// 掛ける値
009:    		mulnum = 2;
010:    
011:    		// 左シフトの回数
012:    		shiftnum = 1;
013:    
014:    		// 9回計測
015:    		for ( number = 1; number <= 9; ++ number ) {
016:    			// 2倍
017:    			ts = System.nanoTime();
018:    			x = 0;
019:    			for ( int i = 1; i <= 10000000; ++ i ) {
020:    				x = x * mulnum;
021:    			}
022:    			te = System.nanoTime();
023:    			tresult1 = te - ts;
024:    
025:    			// ビットの左シフト
026:    			ts = System.nanoTime();
027:    			x = 0;
028:    			for ( int i = 1; i <= 10000000; ++ i ) {
029:    				x = x << shiftnum;
030:    			}
031:    			te = System.nanoTime();
032:    			tresult2 = te - ts;
033:    
034:    			// 結果表示
035:    			System.out.println( number + "回目  2倍:" + tresult1
036:    					 + "ナノ秒  左シフト:" + tresult2
037:    					 + "ナノ秒   "
038:    					 + (double)tresult2 / (double)tresult1 );
039:    		}	
040:    	}
041:    }

TimeBitshiftL2.Javaの出力結果

1回目  2倍:12144639ナノ秒  左シフト:8008474ナノ秒   0.6594246234902494
2回目  2倍:11487779ナノ秒  左シフト:7952025ナノ秒   0.6922160497690633
3回目  2倍:11540380ナノ秒  左シフト:7894293ナノ秒   0.6840583239026791
4回目  2倍:11443304ナノ秒  左シフト:7936203ナノ秒   0.6935237410454184
5回目  2倍:11503174ナノ秒  左シフト:7922518ナノ秒   0.6887245207279312
6回目  2倍:11448008ナノ秒  左シフト:7917814ナノ秒   0.6916324656656424
7回目  2倍:11448008ナノ秒  左シフト:7995217ナノ秒   0.6983937292846056
8回目  2倍:11449292ナノ秒  左シフト:7932781ナノ秒   0.6928621437902012
9回目  2倍:11414224ナノ秒  左シフト:7926367ナノ秒   0.6944288985392262

9回の全ての計測結果が、左シフトの処理時間のほうが短いことを示しています。

この結果から、2倍の処理時間が左シフトの処理時間より3割程度長くなるがわかります。

最後に、"TimeBitshiftL1.Java""TimeBitshiftL2.Java"の処理時間を比較します。

TimeBitshiftL1.Javaの出力結果(1回目だけ)

1回目  2倍:4520189ナノ秒  左シフト:3852210ナノ秒   0.8522232145602762

TimeBitshiftL2.Javaの出力結果(1回目だけ)

1回目  2倍:12144639ナノ秒  左シフト:8008474ナノ秒   0.6594246234902494

この結果の2倍の処理時間の比率は、

  4520189 : 12144639 = 1 : 2.6867…

です。

この結果の左シフトの処理時間の比率は、

  3852210 : 8008474 = 1 : 2.0789…

です。

倍数とシフト数を変数に変更することで2倍以上の処理時間がかかることが確認できました。

ここから、ソースコードの主要部分について解説してきます。

008:    		// 掛ける値
009:    		mulnum = 2;

int型変数mulnumに掛ける値2を代入しています。

011:    		// 左シフトの回数
012:    		shiftnum = 1;

int型変数shiftnumに左シフト回数1を代入しています。

016:    			// 2倍
017:    			ts = System.nanoTime();
018:    			x = 0;
019:    			for ( int i = 1; i <= 10000000; ++ i ) {
020:    				x = x * mulnum;
021:    			}
022:    			te = System.nanoTime();
023:    			tresult1 = te - ts;

int型変数xに0を代入して、その変数xに対してmulnum倍する処理を1000万回行っています。処理終了時間tsと処理開始時間tsの差を処理時間tsresult1に代入しています。

025:    			// ビットの左シフト
026:    			ts = System.nanoTime();
027:    			x = 0;
028:    			for ( int i = 1; i <= 10000000; ++ i ) {
029:    				x = x << shiftnum;
030:    			}
031:    			te = System.nanoTime();
032:    			tresult2 = te - ts;

int型変数xに0を代入して、その変数xに対してshiftnum回の左ビットシフトを1000万回行っています。処理終了時間tsと処理開始時間tsの差を処理時間tsresult2に代入しています。

■関連コンテンツ

ビットシフト ビットシフトについて解説
時間計測 時間を計測する方法を解説
計算結果の表示 四則演算(足し算/引き算/掛け算/割り算)について
for文 繰り返し処理に使用するfor文について解説

■新着情報

2020.09.03 お札とコインの数 必要なお札と硬貨の枚数?
2020.08.27 ポーカーの役判定 ポーカーの役を判定
2020.08.25 ゾロ目の出る確率 サイコロの目のでる確率は?
2020.08.24 文字列配列をint配列に変換 String[]→int[]
2020.08.24 文字列配列をdouble配列に変換 String[]→double[]
2020.08.19 キーボード入力値を配列に格納 キーボード入力→配列
2020.08.19 キーボード入力値をリストに格納 キーボード入力→リスト
2020.08.19 キーボード入力 ScannerクラスとSystem.inを使用

 

 

 

 

 

 

 

 

 

Topへ