整数除算の動作は何ですか?


209

例えば、

int result;

result = 125/100;

または

result = 43/100;

結果は常に部門のフロアになりますか?定義された動作とは何ですか?


5
概要:符号付き整数除算はゼロに向かって切り捨てます。負でない結果の場合、これはfloorと同じです(-Infinityへの丸め)。(C89がこれを保証しないことに注意してください。回答を参照してください。)
Peter Cordes 2017年

5
コードがどちらの手法を使用するかを慎重に決定しているように、誰もが「ゼロに向かって切り捨てる」、「天井」、または「フロア」と言い続けています。コードが話すことができればそれは言うでしょう"I just throw the dam fraction part in the trash and move on with life"
ティモシーLJスチュワート

3
@ TimothyL.J.Stewart「コード」は意図的な決定を行っています。仕様によると、整数除算はT(runcation)-divisionです。このため、modulo / remainder演算子は、PythonやRubyなどの他の言語の場合とは異なる方法で提供されます。言語がmodulo演算子を実行するさまざまな方法のリストについては、これを参照してください。またプログラミング言語がdiv / moduloを実行することを決定する一般的な方法の少なくとも5つをリストしたこのペーパーを参照してください。
13steinj 2018年

1
@ 13steinj私はそれが「ゼロに向かって切り捨てられている...それは床ではない...その負の天井ではない...」に変わっていたコメントに従って口語的に話しています私たちが望むように、しかし「分数の部分が捨てられる」ことを直感的に知ることで、あなたは技術的なポイントを引き出すことができます。技術は重い負担ですが、直感は軽く、風のようにすっきりしています。私はそれらを遠くまで運び、必要な場合はどこから始めればよいかを知っています。あなたがリンクした紙のように、ありがとう。
ティモシーLJスチュワート

私はここでユークリッド除算(整数除算とモジュラス演算子の間の相互作用)に重点を置いて答え ました
Picaud Vincent、

回答:


182

結果は常に部門のフロアになりますか?定義された動作とは何ですか?

はい、2つのオペランドの整数の商。

6.5.5乗法演算子

6整数を除算すると、/演算子の結果は、小数部分が破棄された代数商になります。88)商a / bが表現可能な場合、式(a / b)* b + a%bはaに等しくなります。

および対応する脚注:

88)これはしばしば「ゼロへの切り捨て」と呼ばれます。

もちろん、注意すべき点が2つあります。

3通常の算術変換は、オペランドに対して実行されます。

そして:

5 /演算子の結果は、最初のオペランドを2番目のオペランドで除算した商です。%演算子の結果が余りです。どちらの演算でも、第2オペランドの値がゼロの場合の動作は未定義です。

[注:強調鉱山]


26
...もちろん、負の数を正の(またはvv)で除算している場合を除き、その場合は上限になります。
ウィルA

74
床や天井ではなく、端数の切り捨てであり、概念的には違います!
lornova 2010

38
@Will A:いいえ。ゼロへの切り捨てと定義されています。それ以外のものと呼ぶと混乱を招くだけなので、ご遠慮ください。
マーティンヨーク

44
少なくとも数学的な観点からは、ゼロへの切り捨ては、「if> 0の場合はfloor elseの天井」に相当します。切り捨てと呼ぶのは、floor / ceilingと呼ぶよりも簡単だと思いますが、どちらも有効です。いずれにせよ、ウィルAのポイントは有効です。ディルクジェントリの回答は部分的に正しくありません。なぜなら、OPは結果がディビジョンのフロアであることについて正しいと述べたからです。
ブライアン

9
@フィリップ・ポッター:C89で定義されたとは思いません。1998年のC ++標準では定義されていません。それらでは、もちろん(a / b) * b + a % b == a満足する必要があり、の絶対値はa % b未満である必要がありましたが、負が負であるaか、指定されていませんでした。a % bab
David Thornley、2010

39

ダークジェントは素晴らしい説明をしますC99の整数除算、をますが、C89では、負のオペランドを使用した整数除算には実装定義の方向があることも知っておく必要があります。

ANSI Cドラフト(3.3.5)から:

いずれかのオペランドが負の場合、/演算子の結果が代数商よりも小さい最大の整数であるか、代数商よりも大きい最小の整数であるかは、%演算子の結果の符号と同様に、実装によって定義されます。商a / bが表現可能な場合、式(a / b)* b + a%bはaに等しくなります。

したがって、C89コンパイラーに悩まされている場合は、負の数に注意してください。

C99がゼロへの切り捨てを選択したのは面白い事実です。なぜなら、それがFORTRANがそれを行った方法だからです。comp.std.cでこのメッセージを参照してください。


2
そして、C99ドラフトN1256序文のパラグラフ5はreliable integer division、新しい言語機能として言及しています。アメージング*-*
Ciro Santilli郝海东冠状病六四事件法轮功

切り捨ては、最も一般的なCPUハードウェア(x86など)の動作です。そのため、別の選択をするのはおかしいでしょう。最初に登場したIDK、Fortranのセマンティクスまたはハードウェアの動作ですが、これらが同じであることも偶然ではありません。
Peter Cordes 2017年

2
@PeterCordes:最も一般的なCPUハードウェアは、ほとんどの定数によるフロア除算を、除算の切り捨てよりも速く実行できます。私見、スタンダードが同じ方法で同じオブジェクトを組み合わせる場合、およびの場合と同様に、両方のインスタンスが同じである場合に互いに一致している必要があるexpr1 / expr2と規格が言うべきでしたが、それ以外の場合、切り捨てとフロア分割の選択は指定されていません。これにより、互換性を大幅に損なうことなく、より効率的なコード生成が可能になります(実装によっては、傾斜した場合、特定の動作を文書化できます)expr1 % expr2expr1expr2
supercat

23

結果が負の場合、Cはフローリングではなく0に切り捨てます。Python整数除算が常にここでフローリングする理由について、この読みを学びました:なぜPythonの整数除算フロア


3
(neg%pos)を負にすることは今までに有用かどうか疑問に思うコメントに同意しますか?関連するノートで、「unsignedvar> signedvar」の場合に必要な算術的に正しくない動作がこれまでに役立つかどうか疑問に思いますか?常に正しい動作を要求しない理由を理解できます。間違った行動を要求する根拠はないと思います。
スーパーキャット'30

8
+1は、フローリングが整数除算の正しい動作である理由に関する優れたリファレンスです(Cの定義とは異なり、これは壊れており、ほとんど役に立ちません)。
R .. GitHub ICE HELPING ICEの停止

@supercatを検討してください:filtered = (k - 1) * filtered + value + carry; carry = filtered % factor; filtered /= factor、の値を変更して反復value。時定数のある1次ローパスフィルターに適切な整数近似を行いkますが、除算が切り捨てられcarryて負の値が取得される場合にのみ対称になります。分割の両方の動作は時々役立ちます。
ホッブズ

1
@hobbs:信号がゼロと交差しても、上記のコードは問題なく動作するとは思いません。場合はdiv床の除算演算子であり、factor奇数である、そしてfiltered += (filter+(factor div 2)) div factorまでのすべての値の清潔で対称的行動をもたらすであろうINT_MAX-(factor div 2)
スーパーキャット2017

@supercatでも機能します。このコードは、原子時計のコントローラーでしばらく実行していたものからわずかに抽出されただけです。
ホッブズ

21

はい、結果は常にゼロに向かって切り捨てられます。絶対値が最小になるように丸めます。

-5 / 2 = -2
 5 / 2 =  2

符号なしおよび負でない符号付き値の場合、これはfloorと同じです(-Infinityに丸めます)。


43
床ではなく切り捨て。
dan04 2010

9
@ dan04:うん床は正の整数に対してのみ有効です:)
Leonid

13

結果は常に部門のフロアになりますか?

いいえ。結果は異なりますが、変動は負の値に対してのみ発生します。

定義された動作とは何ですか?

明確にするために、整数除算はゼロに向かって丸めます(切り捨て)間、負の無限大に向かって丸めます

正の値の場合、それらは同じです

int integerDivisionResultPositive= 125/100;//= 1
double flooringResultPositive= floor(125.0/100.0);//=1.0

負の値の場合、これは異なります

int integerDivisionResultNegative= -125/100;//=-1
double flooringResultNegative= floor(-125.0/100.0);//=-2.0

0

私は人々があなたの質問に答えたのを知っていますが、簡単な言葉で:

5 / 2 = 2 // 5と2はどちらも整数であり、整数の除算は常に小数を切り捨てるため

5.0 / 2 or 5 / 2.0 or 5.0 /2.0 = 2.5 //ここでは、5または2のいずれかまたは両方に小数があるため、得られる商は小数になります。

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