質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

1179閲覧

pythonでandを使う時条件式を入れ替えるとエラーが起きる。

noob-question

総合スコア6

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/01/09 13:48

pythonでキーボードから入力された複数のデータ(正の整数値)を小さい順に並んだリストにして返す関数data_inputを作成せよという問題を解いています。(データの最後に0を入力する。sortメソッドなどは使用しない。という条件付き)

def data_input(): l = [] while True: n = int(input('正の整数値:')) i = 0 while i < len(l) and l[i] < n: i += 1 l.insert(i,n)

とすると正常に動作するのですが、while文の条件式の順番を変えて

def data_input(): l = [] while True: n = int(input('正の整数値:')) i = 0 while l[i] < n and I < len(l): i += 1 l.insert(i,n)

とすると、list index out of range というエラーが出てしまいます。なぜでしょうか。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

コンピュータ言語は必ずし数学や論理学と同じ論理で動くわけではありません。
その理由は、コンピュータの物理的な制約によるものもあれば、言語処理系の制約によるもの、使う人間の便利さを考慮したものなどさまざまです。

例えば、以下の計算を見てみましょう。

python

1>>> print(1.0/49.0*49.0) 20.9999999999999999

数学では交換法則によって1.0/49.049.0 = 49.01.0/49.0 = 49.0/49.0 = 1.0 ですが、コンピュータでは、データによって順番を変えることは処理系にとって難しいですし、CPUの計算精度の問題があり、0.9999999999999999となります。

ではWhile文について考えてみましょう。
多くのコンピュータ言語にあるwhile文は、while文の後ろに書かれた条件が成り立つならループを抜け、成り立たないならループを抜けるという機能を持つ文です。擬似コードで書くと以下のような感じです。

@loop@ if condition goto @break@ ・・・ ・・・ goto @loop@ @break@

そこで、noob-questionさんのコード

python

1 while l[i] < n and I < len(l): 2 i += 1

をif文を使って書き換えてみると以下のようになります。

python

1 while True: 2 if i < len(l) and l[i] < n: 3 break 4 i += 1

i < len(l) and l[i] < n がブール代数の交換法則を満たすならば l[i] < n and I < len(l) と書いても同じ結果を出すはずです。つまり、どちらで書いてもlist index out of rangeというエラーが出ることになります。エラーがでないようにするには、二重のif文にするしかありません。

python

1 while True: 2 if i < len(l): 3 if l[i] < n: 4 break 5 i += 1

二重のif文は読みにくいですね。
これを元のようなwhile文で書こうと思うと

python

1 while i < len(l): 2 if l[i] < n: 3 break 4 i += 1

ますます読みにくくなります。

A and Bは、Aが偽ならBが何であっても全体として偽になります。
コンピュータの性能的にはAを計算して偽ならBの計算をしない方が高速です。
Aが偽の時にBを計算しないことにすればプログラムは読みやすくなります。
そして、それで困ることは何もありません。
ということで、pythonに限らず、知っている限り全てのコンピュータ言語は、andはAが偽ならBは処理しないというように決めています。

結局、便利だし問題はないということで、こういう処理をするように言語開発者がそう決めたのです。

投稿2021/01/10 00:10

ppaul

総合スコア24670

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ppaul

2021/01/10 10:02

昔使っていたDelphiはいい言語だった。ヘルスバーグさんが作ったC#にそんな欠陥があるとは(笑)
guest

0

ベストアンサー

pythonドキュメントのプール演算に説明があります。

式 x and y は、まず x を評価します; >x が偽なら x の値を返します; >それ以外の場合には、 y の値を評価し、その結果を返します。

たとえば

a = 1 b = 100 if a == 0 and b == 9: print("OK") else: print("NG")

のとき、出力は「NG」となりますが
内部では「a==0」かどうか判定しFalseと判定された時点でelse以降の行に移っています。
左の「a==0」がFalseと判定された時点で、右の「b==9」は評価(計算)されません。

これと同じように考えると、
最初のコード、

while i < len(l) and l[i] < n: i += 1

では、まず左側のi<len(l)が評価され、
i<len(l)がFalseの場合は、右のl[i] < nは評価されず
すぐにl.insert(i,n)が実行されます。

一方、後の方のコード

while l[i] < n and i < len(l): i += 1

では、まず左側のl[i] < nが評価されます。
しかし、最初の段階ではlは空のリスト([])なので、
空のリストに対してl[0]としているためlist index out of rangeエラーになります。

投稿2021/01/09 14:12

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

noob-question

2021/01/10 13:24

ありがとうございました。条件式を書くときに評価の順番を意識する必要があるのですね。
guest

0

while i < len(l) and l[i] < n:

andの場合、左側の条件式から評価し、偽であればその時点で評価は終わり、偽の結果を返します
i < len(l) が偽の場合はl[i] < nは評価されません。

さて、もう一つの場合はどうなるのか考えてみてください

投稿2021/01/09 13:57

y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問