Open3
Ribbon: 割り算を修正する

流石にひととおりのテストは通しておきたいので。。
Test: 116/125 passed.
Failed:
[~qq_63] Expected: -3 Actual: -2
[~rr_62] Expected: 1 Actual: -1
[(floor-remainder -5 2)] Expected: 1 Actual: -1
[(floor-quotient -5 2)] Expected: -3 Actual: -2
[~qq_63] Expected: -3 Actual: -2
[~rr_62] Expected: -1 Actual: 1
[(floor-remainder 5 -2)] Expected: -1 Actual: 1
[(floor-quotient 5 -2)] Expected: -3 Actual: -2
[(integer? (/ 1 3))] Expected: #f Actual: #t

(/ 1 3)
... いきなり悩みどころだな。。このテストは消すことにした。
整数だよ派
C言語では (int)(1 / 3) = (int)0
なので、 /
がC言語的な除算とするならば 現状の (integer? (/ 1 3))
→ 真 は期待値と言える。
しかし、RibbonはSchemeで、かつ、R7RS Schemeでは 整数 / 整数 → 整数
となるような /
を全パターン標準化しているのでちょっと何とも言えない挙動と言える。
他の言語だとRubyがここに属する。
$ irb
irb(main):001:0> 1/3
=> 0
1/3
だよ派
有理数(ratnum)を実装した通常のSchemeは (/ 1 3)
は 1/3
となる。
$ gosh
gosh> (/ 1 3)
1/3
有理数はPythonやRubyのような多くの言語でサポートされている。
$ python
Python 3.9.10 (main, Jan 20 2022, 21:37:52)
[GCC 11.2.0] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from fractions import Fraction
>>> Fraction(1)/3
Fraction(1, 3)
$ irb
irb(main):001:0> Rational(1)/3
=> (1/3)
0.3333... だよ派
0.333... だよ派もある。身近なところでは電卓であるとか、Pythonがこの派閥に属する。
$ python
Python 3.9.10 (main, Jan 20 2022, 21:37:52)
[GCC 11.2.0] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1/3
0.3333333333333333
JavaScriptには整数が無いので自然とこの派閥になる。
$ node
Welcome to Node.js v18.16.0.
Type ".help" for more information.
> 1/3
0.3333333333333333

floor-quotient
と floor-remainder
floor-quotient
はPythonで言うところの //
に相当する。これに負を与えたときの挙動が間違っている。
(import (yuni scheme))
(call-with-values
(lambda () (floor/ -5 2))
(lambda (qq rr)
(write (list 'QQ: qq 'RR: rr)) (newline)
(write (list 'Q: (floor-quotient -5 2) 'R: (floor-remainder -5 2))) (newline)
)
)
のようなコードが、
- Ribbon
(QQ: -2 RR: -1)
(Q: -2 R: -1)
- Gauche
(QQ: -3 RR: 1)
(Q: -3 R: 1)
Ribbonの挙動はコレ truncate/
だな。。
C99以降のC言語の除算は"Truncate toward to zero"なので、floorしたければ手動で除算する必要がある。
... うーん。。結局2段階にした。
- 符号が一致した割り算は
floor/
とtruncate/
の間には差は無いのでそのまま/
や%
する - 符号が一致しない場合は、まず余りを求め、余りぶんを減算してから商を求める。余りの符号は適当に揃える。
後者の方法で答えが出る正確で簡単な説明を思いつかない。