1. ホーム
  2. javascript

[解決済み] Schemeでモジュロと余りはどのように機能するのでしょうか?

2022-02-14 11:28:38

質問

R5RSの仕様書を読んでいて と表示されます。 :

(modulo 13 4)                   ===>  1
(remainder 13 4)                ===>  1

(modulo -13 4)                  ===>  3
(remainder -13 4)               ===>  -1

(modulo 13 -4)                  ===>  -3
(remainder 13 -4)               ===>  1

(modulo -13 -4)                 ===>  -1
(remainder -13 -4)              ===>  -1

(remainder -13 -4.0)            ===>  -1.0  ; inexact

これは正しいのでしょうか?moduloとreminderはマイナス記号が違うだけだと思っていました。そして、ここでは次のように表示されています。 (modulo -13 4) は3を返すべきところ、JavaScriptでは1を返しています。

モジュロと余りを計算するための適切なアルゴリズムは何ですか?Scheme in JavaScriptの処理に必要なんです。

このコードは クオラ .

function modulo(num1, num2) {
  if (num2 === 0 || isNaN(num1) || isNaN(num2)) {
    return NaN;
  }

  var isPositive = num1 >= 0;

  num1 = Math.abs(num1);
  num2 = Math.abs(num2);

  while (num1 >= num2) {
    num1 = num1 - num2;
  }

  return isPositive ? num1 : -num1;
}

を返しますが、R5RS仕様のようにうまくいきません。 -1 に対して modulo(-13, 4) . また、私はJavaScriptの % と同じです。 remainder . この2つの関数をJavaScriptで、あるいはSchemeで実装するにはどうしたらよいでしょうか。

私の正確な質問は、両方の関数のアルゴリズムがどのように見えるべきか、またはそれらを両方計算するJavaScriptのコードがどのように見えるべきか、ということです。

どのように解決するのですか?

もし誰かが興味を持っているなら、私はRedditで同じ質問をし(この質問へのリンクあり)、正確なスキームコードで答えを得ました。

https://www.reddit.com/r/scheme/comments/fpt1b8/help_with_modulo_and_reminder_in_r5rs/

(define (modulo a b)
  (- a (* b (floor (/ a b)))))

(define (remainder a b)
  (- a (* b (truncate (/ a b)))))

;; as @soegaard show reminder is just JavaScript % so this can be
;; if % is proper function
(define (remainder a b)
  (% a b))

R5RSの例でも同じように動作します。

(list
  (= (modulo 13 4) 1)
  (= (remainder 13 4) 1)      ;; ===>  1

  (= (modulo -13 4) 3)        ;; ===>  3
  (= (remainder -13 4) -1)    ;; ===>  -1

  (= (modulo 13 -4) -3)       ;; ===>  -3
  (= (remainder 13 -4) 1)     ;; ===>  1

  (= (modulo -13 -4) -1)      ;; ===>  -1
  (= (remainder -13 -4) -1)   ;; ===>  -1

  (= (remainder -13 -4.0) -1.0)) ;; ===>  -1.0  ; inexact

floorMath.floortruncate があります。

var truncate = (function() {
    if (Math.trunc) {
        return Math.trunc;
    } else {
        return function(x) {
            if (x === 0) {
                return 0;
            } else if (x < 0) {
                return Math.ceil(x);
            } else {
                return Math.floor(x);
            }
        };
    }
})();