要点
-7を2で割ると、Pythonの//は-4、JavaScriptのMath.truncとGoの整数/は-3だった(出典: 自社の実測・2026-10-20)- 同じ計算の余りは、Pythonの
%が1、JavaScriptとGoの%が-1だった(出典: 自社の実測・2026-10-20) - 測定した6組では、商と余りが分かれたのは片方だけが負で、割り切れない組だった(出典: 自社の実測・2026-10-20)
(-7) % 2 != 0に相当する判定は、3言語とも真だった(出典: 自社の実測・2026-10-20)
「切り捨て」はどちらへ向かうのか
7 を 2 で割った整数の商と余りは、今回比較した3言語でいずれも 3 と 1 だった。しかし、割られる数を -7 に変えると結果が分かれた。Pythonの // と % では商が -4、余りが 1。JavaScriptの Math.trunc(a / b) と %、Goの整数 / と % では商が -3、余りが -1 になった。
この違いを読むには、「切り捨て」の向きを区別する必要がある。-3.5 から小さい方へ進むと -4、0の方へ進むと -3 になる。正の数どうしの結果だけでは見えなかった違いが、負の数を含む計算で現れた。
Pythonの整数の // とは、数学的な割り算の結果にfloor関数を適用し、整数の商を返す演算子のことだ。
また、JavaScriptの / を、そのままGoの整数 / と並べることはできない。今回のJavaScriptの測定では、-7 / 2 は -3.5 を返した。そのため、整数の商の比較には Math.trunc(a / b) を使っている。「同じ / の記号」と「整数の商を得る処理」を分けて読むのが、この比較の出発点になる。
出典: 自社の実測(2026-10-20)、Python 3.9.0同梱リファレンス(取得日 2026-10-20)
公式の規定は商の丸め方と余りの符号を結び付ける
Pythonの同梱リファレンスは、整数のfloor divisionが整数を返し、数学的な除算結果にfloor関数を適用すると説明している。また、% の結果は第2オペランド、つまり割る数と同じ符号、または0になると規定している。
商と余りは別々に決まるわけではない。同じリファレンスには、両者を結ぶ関係として x == (x//y)*y + (x%y) が記されている。divmod の説明も、返すタプルを (x//y, x%y) としている。Pythonで商と余りを一緒に扱うときは、この対応が基準になる。
一方、JavaScriptの余りについて、MDNには次の記述がある。
The remainder ( % ) operator returns the remainder left over when one operand is divided by a second operand. It always takes the sign of the dividend.
出典: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder (取得日 2026-10-20)
ここで符号の基準になるのは、割られる数だ。Pythonの「割る数」と、JavaScriptの「割られる数」を取り違えると、負の値に対する余りを読み違える。
Goの同梱言語仕様は、整数の商と余りについて x = q*y + r、|r| < |y| を満たし、x / y を0の方向へ切り詰めると記している。PythonとGoでは、商と余りを組み合わせて元の値に戻す関係があっても、商の決め方が異なる。
出典: Python 3.9.0同梱リファレンス、Go同梱言語仕様(いずれも取得日 2026-10-20)
同じ6組で比べると、どこで結果が分かれたか
測定環境はmacOS 26.5.1(BuildVersion 25F80・arm64)。使用した版はPython 3.9.0、Node v22.22.3、Go 1.26.2だった。同じ6組の値を各言語のコードで計算し、出力を記録した。
まず、問いの中心である a = -7、b = 2 を言語ごとに並べる。
| 言語 | 比較した商の式 | 商の実測値 | 余りの式 | 余りの実測値 |
|---|---|---|---|---|
| Python | a // b |
-4 | a % b |
1 |
| JavaScript | Math.trunc(a / b) |
-3 | a % b |
-1 |
| Go | a / b(int) |
-3 | a % b(int) |
-1 |
ほかの組でも、符号と割り切れるかどうかを分けて見ると違いが追いやすい。以下は測定記録の値を写した表だ。
| a, b | Python a // b |
Python a % b |
JS Math.trunc(a / b) |
JS a % b |
Go a / b(int) |
Go a % b(int) |
|---|---|---|---|---|---|---|
| 7, 2 | 3 | 1 | 3 | 1 | 3 | 1 |
| -7, 2 | -4 | 1 | -3 | -1 | -3 | -1 |
| 7, -2 | -4 | -1 | -3 | 1 | -3 | 1 |
| -7, -2 | 3 | -1 | 3 | -1 | 3 | -1 |
| -6, 2 | -3 | 0 | -3 | 0(実体は -0) |
-3 | 0 |
| -1, 3 | -1 | 2 | 0 | -1 | 0 | -1 |
この6組で差が出たのは、片方だけが負で、割り切れない組だった。両方が負の (-7, -2) は商が正になり、今回の商と余りは一致した。
ただし、表の0には表示上の注意がある。JavaScriptの -6 % 2 は、テンプレート文字列では 0 と表示されたが、console.log では -0 となり、Object.is(-6 % 2, -0) は true だった。表の表示が一致していても、この違いは残る。
出典: 自社の実測(2026-10-20)
どの演算を使うかは、必要な商と余りで決める
Pythonで小さい方へ切り捨てた整数の商が必要なら、今回の比較では // がその処理に当たる。対応する余りも一緒に得たい場合、divmod(a, b) は商と余りの組を返す。実測の divmod(-7, 2) は (-4, 1) だった。
0の方へ切り詰める処理とは区別したい。Pythonでも、今回の int(a / b) と math.trunc(a / b) は、(-7, 2) に対して -3 を返した。math.floor(a / b) は -4 だったため、同じ言語の中でも式を置き換えると商が変わる。
余りにも同様の注意がある。Pythonの math.fmod(-7, 2) は -1.0 で、Pythonの % が返した 1 とは符号が異なった。関数名に「余り」という共通点があっても、今回の結果では互換ではなかった。
JavaScriptでPythonの結果に合わせた式は、商が Math.floor(a / b)、余りが ((a % b) + b) % b だった。この2つは、測定した6組すべてでPythonの // と % に一致した。Goでは math.Floor(float64(a) / float64(b)) が、同じ6組でPythonの商に一致した。ここで確認した範囲は、その6組である。
条件式への影響も見逃せない。(-7) % 2 == 1 に相当する判定は、Pythonでは真、JavaScriptとGoでは偽だった。後者の余りは -1 だからだ。余りが0でないことを調べる形では、3言語とも真になった。負の奇数を含めて判定したい場合、この違いが条件式に直結する。
出典: 自社の実測(2026-10-20)
自分の環境で確かめる手順
次のコマンドは、PythonとNodeを使って読者自身が結果を確認するためのものだ。商と余りを並べ、Pythonでは // と int(a / b)、JavaScriptでは / と Math.trunc(a / b) の違いも確認できる。ここには実行結果を載せていない。
python3 -I -c "a,b=-7,2; print(a//b, a%b, divmod(a,b), int(a/b))"
node -e "const a=-7,b=2; console.log(a/b, Math.trunc(a/b), a%b, Math.floor(a/b), ((a%b)+b)%b)"
確認するときは、まず (-7, 2)、次に (7, -2) と、負の符号を置く側を変える。その後、両方が負の (-7, -2) と、割り切れる (-6, 2) を比べると、測定表のどの条件に対応するかを追える。
今回の記録では、0で割ったときの挙動、Goのintの最小値を -1 で割る境目、別の版での結果、処理速度は確認できなかった。JavaScriptの Math.floor(-3.5) も単独では測っておらず、確認したのは Math.floor(a / b) として計算した結果だ。式を選ぶ際には、公式の規定と、実際に測った条件を区別して参照したい。
出典: 自社の実測(2026-10-20)

コメント