スナックelve 本店

バツイチ40代女の日記です

あれまぁ~

皆さんこんばんは。スマホで読みづらくムダに長く誰も読んでない疑惑が出るプログラミング記事の時間ですよ。
リフレクションだかなんだかでハマってめちゃ時間かかりましたが、ifで分岐するのと配列にアクセスするのとどっちが速いのかな検証です。

  • 100配列
  • 8配列
  • 3配列
  • if文if入れ子
  • if文ifelseあり

とかを作って1000回×5回で平均時間取ってみました
ソースは下に載せとく。バグってると思うので注意。

java

何故か配列100個用意したのが一番遅かった。コンパイルするから?(関係なさげw)素直にelseif使うのが一番早かったです。

elseIfBlockBの処理時間 59.4
elseIfBlockAの処理時間 62
testArray3の処理時間 68.4
testArray7の処理時間 71.2
elseIfSingleの処理時間 71.8
ifSingleの処理時間 75.4
ifBlockの処理時間 79
testArray100の処理時間 121.6

python

これは配列3つにアクセスするのが早かったけど、三項条件式がifなのでうーむ、と言う感じ。配列組が頑張ってる。ビット演算するとひどく大変なのかもしれない(;´Д`)

testProcess_array3 0.213850307
testProcess_array100 0.23054862
testProcess_ifSingleB 0.23359828
testProcess_ifSingleA 0.240833712
testProcess_array7 0.263782549

エクセルのマクロ(vba

インタプリタ? 100配列がめっちゃ作りにくいというかどう頑張っても配列を引数にできなくてw ワークシートから直接値とるようにしました。Iif、実は速いのか?!

array3 0.850260417
testIf 0.858072917
testElseIfBlock 0.861979167
testIfBlock 0.864583333
array7 0.899739583
array100 0.95703125

ソース

testArray7が実は100入れたらバグってるんだが止まらなかったなぁ・・・。

class test {
 
    public String testArray100(int x) {
        String re[] = { "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C",
                "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C",
                "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B",
                "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "A", "A",
                "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A" };
        return re[x];
    }

    public String testArray7(int x) {
        String re[] = { "C", "", "B", "", "", "", "A" };
        int a = (x / 80) << 2 | (x / 50) << 1;
        return re[a];
    }

    public String testArray3(int x) {
        String re[] = { "C", "B", "A" };
        int a = x >= 80 ? 2 : x >= 50 ? 1 : 0;
        return re[a];
    }

    public String ifSingle(int x) {
        if (x >= 80)
            return "A";
        if (x >= 50)
            return "B";
        return "C";
    }

    public String elseIfSingle(int x) {
        if (x >= 80)
            return "A";
        else if (x >= 50)
            return "B";
        else
            return "C";
    }

    public String ifBlock(int x) {
        if (x >= 80) {
            return "A";
        }
        if (x >= 50) {
            return "B";
        }
        return "C";
    }

    public String elseIfBlockA(int x) {
        if (x >= 80) {
            return "A";
        } else {
            if (x >= 50) {
                return "B";
            } else {
                return "C";
            }
        }
    }

    public String elseIfBlockB(int x) {
        if (x >= 80) {
            return "A";
        } else if (x >= 50) {
            return "B";
        } else {
            return "C";
        }
    }

わからなすぎて分からない呼び出し部分

import java.util.Random;
import java.lang.reflect.Method;

public class App {
    public static void main(String[] args) throws Exception {
        String fName[] = { "testArray100", "testArray7", "testArray3", "ifSingle", "elseIfSingle", "ifBlock",
                "elseIfBlockA", "elseIfBlockB" };
        // 文字列をクラスオブジェクトに変換する
        String strClass = "test";
        Class<?> c = Class.forName(strClass);

        /* クラスのインスタンス化と実行 */
        // インスタンス化
        Object obj = c.getDeclaredConstructor().newInstance();
        // メソッドの定義と実行
        String[] str=new String[8];
        for (int i = 0; i < 8; i++) {
            Method m2 = c.getMethod(fName[i], int.class);
            long startTime = System.currentTimeMillis();
            for (int j = 0; j < 1000; j++) {
                Random random = new Random();
                int x = random.nextInt(101);
                System.out.print(x + "は" + m2.invoke(obj, x) + "です");
            }
            str[i] = fName[i] + "の処理時間:" + (System.currentTimeMillis() - startTime) + " ms";
        }
        System.out.println("");
        for (int i = 0; i < 8; i++) {
            System.out.println(str[i]);
        }
    }
}

一番スッキリかけた感じ

from ast import Num
import random
from time import time


def testProcess_array100(x):
    re = ["not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB",
          "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB",
          "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB",
          "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB",
          "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB", "not AB",
          "not AB", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B",
          "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "A", "A", "A", "A", "A", "A", "A", "A", "A",
          "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A"]
    return re[x]


def testProcess_array7(x):
    re = ["not AB", "", "", "B", "", "", "A"]
    a = ((x//80) << 2) | ((x//50) << 1)
    return re[a]


def testProcess_array3(x):
    re = ["not AB", "B", "A"]
    a = 2 if x >= 80 else 1 if x >= 50 else 0
    return re[a]


def testProcess_ifSingleA(x):
    re = ["not AB", "B", "A"]
    if x >= 80:
        a = 2
    elif x >= 50:
        a = 1
    else:
        a = 0
    return re[a]


def testProcess_ifSingleB(x):
    re = ["not AB", "B", "A"]
    if x >= 80:
        a = 2
    else:
        if x >= 50:
            a = 1
        else:
            a = 0
    return re[a]


proc_time = []

funcs = {"testProcess_array100", "testProcess_array7",
         "testProcess_array3", "testProcess_ifSingleA", "testProcess_ifSingleB"}
for index,func in enumerate(funcs):
    start1 = time()
    for i in range(1000):
        x = random.randint(0, 100)
        re = locals()[func](x)
        print(str(x) + "は" + re + "だよ")
    proc_time.insert(index, func + ": " + str(time() - start1))
print(proc_time)

runでどう頑張ってもfunction呼べなくて断念。

Option Explicit

Sub main()
Dim i As Integer
Dim r As Integer: r = 1
Dim startTime As Double
Dim j As Integer
For j = 0 To 5
    Sheet3.Cells(r, 4) = "array100"
    startTime = Timer
    For i = 0 To 1000
        Debug.Print (array100(Int((100 - 0 + 1) * Rnd + 0)))
    Next
    Sheet3.Cells(r, 5) = Timer - startTime
    r = r + 1
    Sheet3.Cells(r, 4) = "array7"
    startTime = Timer
    For i = 0 To 1000
        Debug.Print (array7(Int((100 - 0 + 1) * Rnd + 0)))
    Next
    Sheet3.Cells(r, 5) = Timer - startTime
    r = r + 1
    Sheet3.Cells(r, 4) = "array3"
    startTime = Timer
    For i = 0 To 1000
        Debug.Print (array3(Int((100 - 0 + 1) * Rnd + 0)))
    Next
    Sheet3.Cells(r, 5) = Timer - startTime
    r = r + 1
    Sheet3.Cells(r, 4) = "testIf"
    startTime = Timer
    For i = 0 To 1000
        Debug.Print (testIf(Int((100 - 0 + 1) * Rnd + 0)))
    Next
    Sheet3.Cells(r, 5) = Timer - startTime
    r = r + 1
    Sheet3.Cells(r, 4) = "testIfBlock"
    startTime = Timer
    For i = 0 To 1000
        Debug.Print (testIfBlock(Int((100 - 0 + 1) * Rnd + 0)))
    Next
    Sheet3.Cells(r, 5) = Timer - startTime
    r = r + 1
    Sheet3.Cells(r, 4) = "testElseIfBlock"
    startTime = Timer
    For i = 0 To 1000
        Debug.Print (testElseIfBlock(Int((100 - 0 + 1) * Rnd + 0)))
    Next
    Sheet3.Cells(r, 5) = Timer - startTime
    r = r + 1
Next
End Sub
Function array100(x As Integer) As String
    Dim ret As String: ret = Sheet3.Cells(x + 1, 1)
    array100 = ret
End Function
Function array7(x As Integer) As String
    Dim re(8) As String
    re(0) = "C"
    re(2) = "B"
    re(6) = "A"
    re(8) = "A"
    Dim a As Integer
    a = ((x \ 80) * (2 ^ 2)) + ((x \ 50) * (2 ^ 1))
    array7 = re(a)
End Function
Function array3(x As Integer) As String
    Dim re(3) As String
    re(0) = "C"
    re(1) = "B"
    re(2) = "A"
    Dim a As Integer
    a = IIf(x >= 80, 2, IIf(x >= 50, 1, 0))
    array3 = re(a)
End Function
Function testIf(x As Integer) As String
    Dim re As String
    If x >= 80 Then re = "A" Else If x >= 50 Then re = "B" Else re = "C"
    testIf = re
End Function
Function testIfBlock(x As Integer) As String
    Dim re As String
    If x >= 80 Then
        re = "A"
    Else
        If x >= 50 Then
            re = "B"
        Else
            re = "C"
        End If
    End If
    testIfBlock = re
End Function
Function testElseIfBlock(x As Integer) As String
    Dim re As String
    If x >= 80 Then
        re = "A"
    ElseIf x >= 50 Then
        re = "B"
    Else
        re = "C"
    End If
    testElseIfBlock = re
End Function

参考

Office TANAKA - Excel VBA Tips[マクロの実行速度を計測する]
VBA でリフレクティブプログラミング | Code++
JavaのforEachメソッドの使い方!拡張for文との違いや注意点を解説【初心者向け】 | プログラミングを学ぶならトレノキャンプ(TRAINOCAMP)
Java Platform, Standard Edition Oracle JDK 9移行ガイド, リリース9
2. 組み込み関数 — Python 3.5.10 ドキュメント
Pythonコードの実行処理時間を計測する方法|dot blog
他のブックのマクロを実行(Runメソッド)|VBA入門
VBAのVariant型について|VBA技術解説
文字列としてのプロシージャー名を起動する方法(Run,OnTime)|VBA技術解説
Java:リフレクションの使い方 - そふと工房
Excel VBA でFunctionが呼び出せません -お世話になります。VBA初級者- Visual Basic(VBA) | 教えて!goo
関数を順番に呼び出したい -一度、ここで質問をしたのですが、わたくし- JavaScript | 教えて!goo
配列に収めた関数を順に実行する - Qiita
Python - 関数を文字列から動的に呼び出す - Qiita
配列"への"ポインタ・参照 - Qiita
Java9で追加されたメソッド一覧とその使い方 - Qiita
Visual Studio CodeでJavaプログラム開発環境構築 - Qiita
Java リフレクションでメソッド実行 - Qiita
Java リフレクションで関数をまとめて呼び出す方法 - Qiita
JavaでReflection 第一回:コンストラクタ編 - Qiita
java.lang.ClassNotFoundException:となってしまった時の対応方法 - Qiita
VBAで配列を引数・戻り値にする方法 - Qiita
【Java】packageとimportによる複数ファイルでの開発 - Qiita
入門Javaのリフレクション - Qiita
分岐処理、速度ってどう変わる? - Qiita
Javaでメソッドを動的に呼び出す(リファクタリング) - Qiita
関数ポインタの配列 - Qiita
JavaからJavaソースをevalする - Qiita
Class.newInstance()は非推奨
Java でポインタ渡しは出来る? 値渡しと参照(ポインタ)渡しの違いを解説 | ポテパンスタイル
【ExcelVBA】Functionプロシージャ(引数と戻り値) | TECH PROjin
Javaでコールバック処理を使う方法【初心者向け】 | TechAcademyマガジン
Pythonでの三項演算子の記述方法を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
Pythonで切り捨て除算する方法を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
Pythonでfor文を使って配列の要素を取得する方法を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
Javaのリフレクションの使い方を現役エンジニアが解説【初心者向け】 | TechAcademyマガジン
Javaでメソッド名の文字列を元にメソッドの処理を呼び出す方法
配列に格納した文字列(※関数名)をeval()を使わずに実行したい
python for文を初心者向けに解説!for文基礎はこれで…|Udemy メディア
python 関数の基本が初心者でもわかる!引数や戻り値…|Udemy メディア
Python配列の基礎はこれで完璧!初心者必見のメソッ…|Udemy メディア
Excel VBAで数値を文字列に変換する:Str | UX MILK
VBAの三項演算子(IIf関数) | Excel作業をVBAで効率化
String型(文字列型)に変換する【Str関数】【ExcelVBA】 | VBA Create
IT系/VBA/リフレクション/メタプログラミング - BANKURA WIKI Wiki*
Java で配列を出力する | Delft スタック
Python で範囲内のランダムな整数を生成する | Delft スタック
Evaluateメソッド(文字列の数式を実行します)|VBA技術解説
Javaにおける配列の宣言と初期化方法とは? | Javaコラム
excel : VBAのコマンドとして文字列を実行する方法
Pythonのfor文でインデックス(index)を取得|enumerate(), zip() | HEADBOOST
JavaScript | eval関数(文字列として指定したコードを実行する)
Python | 数値を文字列に変換して文字列と連結する
【Python入門】if文で条件分岐する書き方をサンプルコードとあわせて解説 | IT・ものづくりエンジニアの転職・派遣求人情報なら【パソナテック】
【Python入門】if文で条件分岐する書き方をサンプルコードとあわせて解説 | IT・ものづくりエンジニアの転職・派遣求人情報なら【パソナテック】
VBAのさまざまな割り算:エクセルマクロ・Excel VBAの使い方
【VBA入門】Functionの使い方(呼び出し、引数、戻り値) | 侍エンジニアブログ
【VBA入門】変数をDimで宣言し、 Asでデータ型を定義する方法 | 侍エンジニアブログ
VBAのIf文を使いこなそう! 条件分岐の基本をスッキリ解説 | 侍エンジニアブログ
【Java入門】リフレクションでメソッドの実行、フィールドの変更 | 侍エンジニアブログ
【Java入門】処理時間をナノ秒・マイクロ秒で計測する方法 | 侍エンジニアブログ
【Python入門】基本文法をまとめて解説 | 侍エンジニアブログ
【ExcelVBA入門】処理時間を計測するためのTimer関数の使い方とは | 侍エンジニアブログ
【ExcelVBA入門】数値を文字列に変換するためのStr関数の使い方とは | 侍エンジニアブログ
【ExcelVBA入門】最初に覚えると幸せになれるDebug.Printの使い方! | 侍エンジニアブログ
【ExcelVBA】Variant型の使い方とは?配列で使う方法・注意点も解説! | 侍エンジニアブログ
侍テラコヤ(SAMURAI TERAKOYA) - 日本最安級のサブスク型プログラミングスクール
【初心者向け】Pythonの配列をマスターしよう!配列操作を一挙解説! | TechTeacher Blog
戻り値をマスターしよう!Pythonのreturn文の使い方を簡単解説 | TechTeacher Blog
VBA ビット演算やビットシフトする
VBA エラー 1004 アプリケーション定義またはオブジェクト定義のエラーです。
【VBA】配列を引数にする方法とその注意点(オブジェクトの場合も解説) | やろまいCode