Python.jpプログラミング言語Pythonと、そのコミュニティをめぐる文書集です2010年9月21日火曜日なぜPythonの割り算はC言語と違う方式なのか?今日は何度も「なぜPythonの整数の割り算はC言語のようにゼロに向けて丸めるのではなく、切り捨てなのか?」と聞かれた。数値が両方とも正の場合には、何も驚くようなことは発生しない。5//22しかし、どちらかの数値が負の場合、結果は切り捨てられる。言い換えると、ゼロから遠い方向(負の無限大方向)に向けて丸められる。5//-2-3この挙動は何人かの人を混乱させたようであるが、このような実装になっているのは数学的な根拠がある。整数の割り算の演算子(//)と、その弟の余りを計算する演算子(%)は、次のような数学的な関係を保っている。すべての変数は整数とする。rこれは、次のような関係性を持っている。bはともに0以上の整数)もしも、この式の関係性を、負の数値まで拡張したいのであれば、2つの選択肢があります。abs(r)と変更する必要がある。それ以外には、qを負の無限大の方に向けて丸める方法がある。数学の整数論を考えると、数学者はいつも後者の選択を望ましいと考えてきた(Wikipedia参照)。この方式の割り算が役に立つ、おもしろい利用方法がいくつかあったので、Pythonでもこの後者の挙動を採用した。POSIXのタイムスタンプ(1970年からの経過の秒数)を取得して、時刻に変える、という場面を考えてみる。86400とやれば良い。1970年依存のより前の時刻を計算したいと考えると、ゼロ方向に丸めてしまうと、無意味な結果が帰ってくることになる。負の無限大方向に丸めるというルールであれば、このような場面でも、そのまま適用できる。コンピュータグラフィックスで、ピクセルの位置を計算する場面でも、同じ事が言える。こちらの方が良く発生するだろう。bが負の値をであれば、すべてが逆さまになる。普遍条件は次のようになる。b.それでは、なぜC言語はこのような実装になっていないのだろうか?それは、Cが設計された当時のハードウェアがこのようにしていなかったからである。現在では負の数は補数として表現されているが、当時のコンピュータは少なくとも整数に関しては、「符号+大きさ」という表現になっていた。私が最初に触れたコンピュータはデータを制御するメインフレームであったが、浮動小数点数と同じく、整数に補数を使うようになっていた。Petersは、これらの規則を浮動小数点数の割り算にも広げたいという私の願望に対して、いくつか心配に思っていることを説明してくれた。彼の心配は正しかった。負の無限大の方向に丸めるというルールは、x%1.0という式があったときに、xが非常に小さい負の整数の時に精度が失われてしまうのである。これは整数の割り算を破壊するものではなく、//はそれに密に結合されている。上記の説明では、/の代わりに//を使用した。2でも割り算が整数領域で行われるのを強調したいときに利用できる。2の/演算子は、演算する数が両方整数か、一つ以上浮動小数点数が含まれているかで型が変わるという曖昧なところがある。これに関してはまったく別の話なので、ここでは説明しない。238に書かれている。Woutersらの貢献もあって実現された。Petersもこのアイディアをしっかりと保証してくれた。基本的には、リスト内包表記は数学者によって使用されてきた、よく知られた表記法をPythonicに解釈して実現したものである。10}これは、一般に、10より大きな数の集合と解釈される。set)であると、読み手は解釈する。Pythonの2.0には普遍集合の概念はなく、setもなかった。setについてもおもしろい話があるため、将来ブログに投稿することになるだろう。P(x)]これを実行すると、シーケンスSに含まれる値のうち、述部Pの評価結果に合う要素に対して、関数fを適用した結果を含むリストが生成される。if節はオプションとなっているし、また、for節を複数入れて、それぞれにif節を書いて、ネストされたループを表現することもできる。このネストされたループはあまり使われることはない。一般的には多次元の要素を、1次元のリストにマップすることが良く行われる。リスト内包表記は、組み込み関数のmap()とfilter()の代替手段となっている。P(x)]と同じ意味となる。map()やfilter()を使った表現の方がコンパクトであるため、リスト内包表記の方が推奨されていないのでは?と思う人もいるだろう。現実的なサンプルを見ると見解が変わるだろう。与えられたリストの全ての要素に数字の1が足された、新しいリストを作りたいとする。