割り算(除算)で、答えを「商」と「余り」という形式で表す場合、
「余り」の定義とは何でしょうか?
文献や数学に長けた人々の見解を集約したところ、
-------------------------------------------------------------------
代数学の除法定理によれば、
整数 A, B があり、B > 0 の場合、これに対して
A = ( B * q ) + r
0 <= r < B
であるような整数 q, r がただ一組存在する。
q を A を B で割った「商」、r を「余り」という。
とあります。
ここから「余り(r)は0及び自然数である」という前提が推論されます。
-------------------------------------------------------------------
数学上のモジュロ関数の考え方では、
剰余を求める関数を、mod( A, B ) 但し、A が被除数、B が
除数とするとき、mod( A, B )は、B と同符号をとり、その絶対
値は B の絶対値より小さい。
つまり、商を Q とすると、A = B * Q + mod( A, B ) を満足し
なければならない。
これにより、例えば -5 / 2 の 商は -3,余りは 1 となる。
-------------------------------------------------------------------
また、
「余り」という言語表現を自然に考えれば、「余り」にマイ
ナスはない。つまり常にプラスである。
という感覚的なところに理由を置く説もあります。
-------------------------------------------------------------------
これらに共通なのは、マイナスの剰余は存在しないという点です。
さて、ここからがコンピュータ言語の算術演算子や算術関数について
の話です。
例えばC言語では、
signed int nA, nB, nQuot, nRem;
nQuot = nA / nB;
nRem = nA % nB; とする場合、
nA = -5, nB = +2 では、 nQuotは -2, nRemは -1 となり、
nA = +5, nB = -2 では、 nQuotは -2, nRemは +1 となります。
他にもVisualBasic, Pascal, JAVA でも結果は同様です。
ANSIによる定義では、「剰余は商と同符号をとる」とありますし、
Microsoft固有仕様としては 「モジュロ演算子 % の剰余式の結果は、
必ず第1オペランドと同じ符号となる」とあります。
どちらにしてもこれらは、数学上の考え方とは異なるようです。
コンピュータ言語で、「これが仕様」と決められ、広く認知されて
いる以上、それを否定するつもりは全くありません。
私が知りたいのは「算術」演算子/関数によって導かれる結果を、
「なぜ数学上の概念と違う仕様に決めたのか?」という事です。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
「余り」について上記以外の定義や説があるのかも知れません。
これらについて、明快な解答をお持ちの方がいたら御教授願います。
# 手元にあるバージョンのjparl では、
# -5 / +2 は -2, -5 % +2 は +1
# +5 / -2 は -2, +5 % -2 は +5 になっちゃいます。
# これは話になりませんね。制限仕様?バグ?
--
佐藤 弘幸 (Hiroyuki Satoh)
E-mail address : h-s...@tkb.att.ne.jp
> 整数 A, B があり、B > 0 の場合、これに対して
> A = ( B * q ) + r
> 0 <= r < B
> であるような整数 q, r がただ一組存在する。
> q を A を B で割った「商」、r を「余り」という。
上の定義はBが正の時しか使えませんよね。Bが負の場合も考慮した場合、
A/Bを整数値に丸める方法として以下の4通りが一般的です。
(1) 0に向かって丸める(truncate)。
すなわち、『商』とは、A/Bより絶対値が大きくない整数の中でもっとも
A/Bに近いものと定義する。
(2) 正の無限大に向かって丸める(ceiling)。
商とはA/Bより小さくない整数の中でもっともA/Bに近いものと定義する。
(3) 負の無限大に向かって丸める(floor)。
商とはA/Bより大きくない整数の中でもっともA/Bに近いものと定義する。
(4) もっとも近い整数に丸める(round)。
商とはすべての整数の中でもっともA/Bに近いものと定義する。
(ちょうど2つの整数の中間にある時は、偶数を選ぶ)。
この4つに応じてそれぞれ『余り』が定義できます。
> どちらにしてもこれらは、数学上の考え方とは異なるようです。
数学的には上の4つのどれが「正しい」ともいえないと思います。佐藤さんが
示した除法定理も、「除数は正」という範囲でしか成り立ちませんよね。この
範囲以外だと上を満たすq, rは存在しませんから。
ceilingやfloorは数学で良く使いますよね。統計学ではroundを使わないと困
る事も多いでしょう。また、「整数部と小数部」なんていう言い方をした時は、
truncateが整数部を求める演算に相当するでしょう。
> コンピュータ言語で、「これが仕様」と決められ、広く認知されて
> いる以上、それを否定するつもりは全くありません。
>
> 私が知りたいのは「算術」演算子/関数によって導かれる結果を、
> 「なぜ数学上の概念と違う仕様に決めたのか?」という事です。
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
プログラミング言語では、演算子としてこれらのうち1つしか用意していない
言語が多いですね。「除数または被除数のいずれかが負の時、剰余の符号は不
定(あるいは処理系依存)」としている言語もあります。
実際にtruncateを採用している処理系が多いのは、おそらくそれがコンピュー
タで処理する上でもっとも楽だからでしょう。floorやceilingは商の正負によっ
てアルゴリズムを変えなければいけませんし、roundもtruncateより手間がか
かります。
ちなみに、Common Lispではtruncate, floor, ceiling, roundという4つの丸
め方が用意されています。剰余にはfloorの剰余を返すmodと、truncateの剰余
を返すremの2とおりがあります。SchemeというLispの方言にもmoduloと
remainderという2つの剰余関数があります。Fortranの組み込み関数やCのライ
ブラリ関数では、浮動小数点数を整数値に丸めるときにtruncateする関数
(aint)とroundする関数(anint)の2つが用意されています。
> # 手元にあるバージョンのjparl では、
> # -5 / +2 は -2, -5 % +2 は +1
> # +5 / -2 は -2, +5 % -2 は +5 になっちゃいます。
> # これは話になりませんね。制限仕様?バグ?
Perlにはちゃんとした仕様がない(仕様 = 実装)ので推測するしかありません
が、除数・被除数のどちらかが負だと剰余はまったく不定なのかも。つまり、
除法定理が成り立つ範囲でしか使ってはいけないとか???
前田敦司
> 数学的には上の4つのどれが「正しい」ともいえないと思います。佐藤さんが
> 示した除法定理も、「除数は正」という範囲でしか成り立ちませんよね。この
> 範囲以外だと上を満たすq, rは存在しませんから。
> ceilingやfloorは数学で良く使いますよね。統計学ではroundを使わないと困
> る事も多いでしょう。また、「整数部と小数部」なんていう言い方をした時は、
> truncateが整数部を求める演算に相当するでしょう。
なるほど、やはり剰余については方式的な定義が複数存在するという事な
訳ですね。
言語処理系の仕様は、それらの中で最も演算がシンプルになるtruncateを
採用した。
という事ですね。
> Perlにはちゃんとした仕様がない(仕様 = 実装)ので推測するしかありません
> が、除数・被除数のどちらかが負だと剰余はまったく不定なのかも。つまり、
> 除法定理が成り立つ範囲でしか使ってはいけないとか???
そのようですね。
こういうのがあるから言語間移植って一筋縄にいかないんです。
御教授ありがとうございました。
--
佐藤 弘幸 (Hiroyuki Satoh)
E-mail address for private : h-s...@tkb.att.ne.jp
> h-s...@rd.njk.co.jp (Hiroyuki Satoh) writes:
>> # 手元にあるバージョンのjparl では、
>> # -5 / +2 は -2, -5 % +2 は +1
>> # +5 / -2 は -2, +5 % -2 は +5 になっちゃいます。
>> # これは話になりませんね。制限仕様?バグ?
>>>>> In article <pypiupi...@tp560e.sowa.is.uec.ac.jp>,
>>>>> MAEDA Atusi <ma...@is.uec.ac.jp> writes:
> Perlにはちゃんとした仕様がない(仕様 = 実装)ので推測するしかありません
> が、除数・被除数のどちらかが負だと剰余はまったく不定なのかも。つまり、
> 除法定理が成り立つ範囲でしか使ってはいけないとか???
Perl5.004で規定?された(regulateされた)ようです。
man perlopより:
| Binary "%" computes the modulus of two numbers. Given
| integer operands $a and $b: If $b is positive, then $a % $b
| is $a minus the largest multiple of $b that is not greater
| than $a. If $b is negative, then $a % $b is $a minus the
| smallest multiple of $b that is not less than $a (i.e. the
| result will be less than or equal to zero).
arith.tより:
|try 1, 13 % 4 == 1;
|try 2, -13 % 4 == 3;
|try 3, 13 % -4 == -3;
|try 4, -13 % -4 == -1;
------------------------------- MadCat LRM15 □/ ̄\□ LRM15
前田 薫 ma...@src.ricoh.co.jp 75t 175km/h LG+ o"| |"o AFC100
(株)リコー ソフトウェア研究所 HeatSink 14 Sm+ .=X ̄X=. Sm+
------------------------------- Armor 2025 _|_ _|_
> Perl5.004で規定?された(regulateされた)ようです。
>
> man perlopより:
> | Binary "%" computes the modulus of two numbers. Given
> | integer operands $a and $b: If $b is positive, then $a % $b
> | is $a minus the largest multiple of $b that is not greater
> | than $a. If $b is negative, then $a % $b is $a minus the
> | smallest multiple of $b that is not less than $a (i.e. the
> | result will be less than or equal to zero).
なるほど。floorの余りを採用したんですね。佐藤さんが最初におっしゃった
mathematically correctな剰余ですね。
たしかに、Perl 5.004ではそういう値を返しますね。Perl 5.003だと、除数
($b)が負の時はむちゃくちゃ^^;。マニュアル見ても
| Binary "%" computes the modulus of the two numbers.
と書いてあるだけだし。
前田敦司