タグ: if文

  • elifを使った条件分岐がうまくいかない!![Python]

    elifを使った条件分岐がうまくいかない!![Python]

    if文で複数条件で複数の条件分岐を行いたいときに、elifでやってみたらエラーは出ていないんだけど、なんか結果がうまくいかないという時ってないでしょうか。
    もしかしたら、下の事象が当てはまっているかもしれません。
    参考までに、僕が間違えてしまっていたので、メモ書きします。

    問題となるプログラム

    if、elifに二条件を記載して、elifを含むプログラムを作成した状況で問題が起こります。

    def trable(a, b):
        if a >= 10 & b >= 10:
            print("patern A")
        elif a >= 10 & b < 10:
            print("patern B")
        elif a < 10 & b >= 10:
            print("patern C")
        else:
            print("patern D")
    
    trable(11, 11)
    trable(11, 9)
    trable(9, 11)
    trable(9, 9)

    上記のプログラムを実行したときに、上から順にA, B, C, Dのパターンに分類分けされてほしいようにも思えますが、実際には下の出力になります。

    patern A
    patern B
    patern C
    patern B

    順序を入れ替えてみてはどうでしょうか。

    def trable(a, b):
        if a >= 10 & b >= 10:
            print("patern A")
        elif a < 10 & b < 10:
            print("patern B")
        elif a >= 10 & b >= 10:
            print("patern C")
        else:
            print("patern D")
    
    trable(11, 11)
    trable(9, 11)
    trable(11, 9)
    trable(9, 9)

    とやって、patern B, Cのプログラムを入れ替えて、A, B, C, Dと出力してほしいというプログラムを作ると、実際には下記の出力になります。

    patern A
    patern D
    patern D
    patern D

    elif自体は複数条件を定義したいときに下記のように使用します。

    if 条件式A:
      条件式Aが真(True)となった場合の処理
    elif 条件式B:
      条件式Aが偽(False)で、条件式Bが真(True)となった場合の処理
    else:
      条件式Aが偽(False)で、条件式Bも偽(False)となった場合の処理

    しかし、if文、elif文の条件式が二条件になると、上記のような問題が起こると想定されます。
    よって、目的の出力にならないことが起こります。

    これの厄介なところはエラーが排出されないので、実際に結果を見てみないとうまくいっているかどうかがわからないという点です。

    改善策

    複数条件で複数の条件式で分けたいときには、elif文で複数条件を指定しないようにします。

    def resolve(a, b):
        if a>= 10:
            if b >= 10:
                print("patern A")
            else:
                print("patern B")
    
        else:
            if b >= 10:
                print("patern C")
            else:
                print("patern D")
    
    resolve(11, 11)
    resolve(11, 9)
    resolve(9, 11)
    resolve(9, 9)

    煩わしくなりましたが、こうすることで思っている想定通りの出力を行うことができます。

    プログラムではこのような思わぬ落とし穴があるので、書いたプログラムはしっかり確認することの教訓になりますね。

    追記(2022年8月)

    ()で括っていないことが問題であったみたいです。

    def trable(a, b):
        if (a >= 10) & (b >= 10):
            print("patern A")
        elif (a < 10) & (b < 10):
            print("patern B")
        elif (a >= 10) & (b >= 10):
            print("patern C")
        else:
            print("patern D")

    とすると、うまく条件分岐できました。
    もしくは、&をandと表記することでも解決することができます。

    def trable(a, b):
        if a >= 10 and b >= 10:
            print("patern A")
        elif a < 10 and b < 10:
            print("patern B")
        elif a >= 10 and b >= 10:
            print("patern C")
        else:
            print("patern D")

    &とandって同じように思えますが、&には論理積という側面があり、元々のプログラムだと

    a >= 10 & b < 10

    これは a >= (10 & b) < 10 の意味になるようで、
    a=9, b=9だと不等式が
    9>=8<10となり、Trueとなってしまうそうです。

    難しいですね・・・。

  • Arduino言語におけるswitch case 構文

    Arduino言語におけるswitch case 構文

    Arduinoにおいて、さまざまな条件分けをしたいとき、if文で構成することがほとんどだと思います。
    しかし、条件分岐が10とか20とか(あんまりないとは思いますが)あった時はどうしましょう。

    C/C++言語にはswitch文があり、C/C++言語をベースとしているArduino言語も同じ構文が使えます。

    以下にプログラム例を記載します。

    switch (var) {
      case 1:
        // varが1のときに実行する処理
        break;
      case 2:
        // varが1のときに実行する処理
        break;
      default: 
        // どのcaseラベルにも一致しないときに実行する処理
        // defaultは、省略可能
      }

    varが変数であり、varが1の時、case 1の処理が実行されます。
    varが2の時、case 2の処理が実行されます。
    varが1, 2以外の時は、defaultの処理が実行されます。

    case 1, case 2の処理後の “break;”はそれぞれのcaseの処理が終了したということを示す文です。
    この文がないと、エラーを起こしたりします。

    defaultの処理において、break; が必要ないのは、defaultは最後の条件分岐になり、最後の処理というのが明白なためです。
    ただ、書いてはいけないわけではなく、書いても問題なくプログラムは動きます。

    また、default: 自体も省略することができます。
    if else構文のelseの省略のような感覚です。

    個人的にはswitch case構文はif構文よりもプログラムを見たときのスッキリさはあると思います。
    そこまで難しいコードでもないので、ぜひ使ってみてください。