Pythonで整数除算と浮動小数点から整数への変換の違いの理由は何ですか?


52

私は最近int()、浮動小数点を0に向かって丸めるのに対し、整数除算は浮動小数点をその床に向かって丸めることに気づきました。

例えば:

-7 // 2 = -4
int(-7/2) = -3

私は指定するドキュメントを読みました:

クラスint(x、base = 10)

数値または文字列xから構成される整数オブジェクトを返すか、引数が指定されていない場合は0を返します。xが数値の場合、xを返します。int()。浮動小数点数の場合、これはゼロに向かって切り捨てられます。

そして:

階分割

最も近い整数に切り捨てる数学除算フロア除算演算子は//です。たとえば、式11 // 4は、floatのtrue除算によって返される2.75とは対照的に、2に評価されます。(-11)// 4は-3であることに注意してください。PEP 238を参照してください。

しかし、2つの同様の演算(浮動小数点から整数への除算)が異なる結果を返す必要があることは、私には非論理的です。

機能の違いに動機はありますか?

ありがとうございました。


回答:


61

一貫性。

それを理解するには、いくつかの非常に基本的で一見無関係な説明に従う必要があります。

学校では、残りの部分で分割を学びました。そして、あなたはこのような計算をしました:

8 ÷ 4 = 2 R 0
7 ÷ 4 = 1 R 3
6 ÷ 4 = 1 R 2
5 ÷ 4 = 1 R 1
4 ÷ 4 = 1 R 0
3 ÷ 4 = 0 R 3
2 ÷ 4 = 0 R 2
1 ÷ 4 = 0 R 1
0 ÷ 4 = 0 R 0
        ^------ This is the result of x // 4
            ^-- This is the result of x % 4 (modulo)

後で、実数の除算を学習しました。

8 ÷ 4 = 2.0
7 ÷ 4 = 1.75
6 ÷ 4 = 1.5
5 ÷ 4 = 1.25
4 ÷ 4 = 1.0
3 ÷ 4 = 0.75
2 ÷ 4 = 0.5
1 ÷ 4 = 0.25
0 ÷ 4 = 0.0
        ^--- Note that the number in front of the . is int(x/4)

この時点まで、あなたはそれを信じx // 4int(x/4)常に同じ結果をもたらすかもしれません。それがあなたの現在の状況の理解です。

ただし、整数除算で何が発生するかを確認してください。Rの後ろの数字が3、2、1から0に循環してから再開します。3、2、1、0。Rの前の数字は4番目のステップごとに減少します。

では、どうなるのでしょうか?

 8 ÷ 4 =  2 R 0
 7 ÷ 4 =  1 R 3
 6 ÷ 4 =  1 R 2
 5 ÷ 4 =  1 R 1
 4 ÷ 4 =  1 R 0
 3 ÷ 4 =  0 R 3
 2 ÷ 4 =  0 R 2
 1 ÷ 4 =  0 R 1
 0 ÷ 4 =  0 R 0
-1 ÷ 4 = -1 R 3
         ^------ We have to decrease now, because we already have 0 four times
              ^-- We have to restart the cycle at 3

同時に、実数除算により次のようになります。

-1 ÷ 4 = -0.25
          ^----- There is still a 0 in front of the .

これ-1 // 4が-1 int(-1/4)を与えるが0 を与える理由です。

機能の違いに動機はありますか?

まあ、それらは異なる目的を果たします://剰余を伴う整数計算int()の一部で.あり、実数演算の前の部分を提供します。

何を計算するかを決定し、次に、正しい結果を得るためにPythonで使用する演算子を決定します。

良い質問。学習を続けます。


11
実際には、これはトリックを可能にします。もし-1のスイーツがあり、それを4人の友人に配った場合、3つのスイーツが残ります。素晴らしいですね。お菓子を-1個所有する方法を見つけるだけです。
Thomas Weller

1
それは私//がPython 3に演算子を追加する動機がint(float)の使用を強制することを避けるためであると理解する限り、ある程度の一貫性を作成します。そうでない場合は、ときに私が使用して実装することを選択すべきであるint()とするとき、私は使用して実装する必要があります//
IsaacDj

1
わかりました、それは間違った仮定です。仮定が正しいかどうかをテストする限り、それは悪いことではありません。おそらく、ケースの50%で失敗します(少なくとも私にとってはそうです)。私はそれについていくつかの言葉を答えに加えました。
Thomas Weller

2
@IsaacDj 「フロアディビジョン」オペレーターの背後にあるストーリーについては、これ読むとよいでしょう。
Bruno desthuilliers

1
@EricLippert:私はそれが奇妙だとは思わない。非可逆演算が正確な演算と同じ結果をもたらすとは想定できません。コードで話されている:Math.Floor(3.23) != -Math.Floor(-3.23)同じ理由で、-((-x)//y)は等しくない必要があり x//yます。
Thomas Weller

4

これらの2つの演算は直感的に類似しているはずであるというあなたの観察は、正の数ではそれらは同じように動作するので予想されると私は言うでしょう。しかし、それらの起源(1つは数学から、もう1つはコンピュータサイエンスからのもの)を見ると、それらの異なる動作がよりわかりやすくなります。

あなたはそこの概念の後ろを見ることができます:

  • 数学除算に適用される床関数別名床関数
  • 型変換/型キャスト

================================================== ================

I)Floor除算、つまり数学除算に適用されるFloor関数

床関数は数学において非常に確立された概念です。

mathworld.wolframから:

フロア関数| _ x_ |は、最大整数関数または整数値とも呼ばれ(SpanierおよびOldham 1987)、x以下の最大の整数を与えます。フロア機能の名前と記号はKE Iversonによって作成されました(Graham et al。1994)

したがって、床の除算は、数学の除算に適用される床の関数にすぎません。動作は非常に明確で、「数学的に正確」です。

II)型変換/型キャスト

ウィキペディアから:

コンピュータサイエンスでは、型変換、型キャスト、型強制、および型ジャグリングは、あるデータ型から別のデータ型に式を変更するさまざまな方法です。

ほとんどのプログラミング言語では、floatからintegerへのキャスト形式は、丸め規則によって適用されます(そのため、規則があります)。

  • 0への丸め–ゼロへの直接丸め(切り捨てとも呼ばれる)

IEEE 754に基づく丸め規則。


つまり、言い換えると、Pythonでの整数除算と浮動小数点から整数への変換の違いの理由は数学的なものであり、ここにGuido van Rossumからのいくつかの考えがあります(私は彼を紹介する必要はないと思います:D)(からブログPythonの歴史、記事「Pythonの整数除算の理由」

これは一部の人々の邪魔をしますが、数学的な理由があります。整数除算演算(//)とその兄弟であるモジュロ演算(%)が一緒になり、素晴らしい数学的な関係を満たします(すべての変数は整数です)。

a / b = q、残りはr

そのような

b * q + r = aおよび0 <= r <b

(aおよびbが> = 0であると想定)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.