回答:
ある数y
とある除数についてx
、商(quotient
)と剰余(remainder
)を次のように計算します。
var quotient = Math.floor(y/x);
var remainder = y % x;
floor
andを%
一緒に使用することは、そのように一貫していません。のtrunc
代わりにfloor
(それにより負の剰余を許可する)を使用するか、減算を使用して剰余を取得します(rem = y - div * x
)。
rem
とにかく剰余を計算する場合は、div
フローリングなしで商をより速く取得できます(y - rem) / x
。2.ちなみに、ドナルドクヌースの推奨定義によるモジュロ演算(符号の一致除数、残りのユークリッド係数ではなくJavaScriptの符号の一致除算)は、JavaScriptでとしてコーディングできるものfunction mod (a, n) { return a % n + (Math.sign(a) !== Math.sign(n) ? n : 0); }
です。
私はビット演算子の専門家ではありませんが、整数を取得する別の方法があります。
var num = ~~(a / b);
これは負の数でも正しく機能しますMath.floor()
が、間違った方向に丸められます。
これも正しいようです:
var num = (a / b) >> 0;
a/b | 0
~~int
、int | 0
およびint >> 0
初期引数は変更しませんが、インタプリタが整数部分を演算子に渡すようにします。
floor
その名前を考えると、間違った方向に丸めることはほとんどありません。
a = 12447132275286670000; b = 128
Math.floor(a/b)
-> 97243220900677100
および~~(a/b)
-> -1231452688
。
~~(5/2) --> 2
同様に(5/2)>>0 --> 2
、しかし~~(5/2) + 1 --> 3
、同時に~~(5/2)>>0 + 1 --> 1
。~~
優先順位がより適切であるため、これは良い選択です。
Firefoxで速度テストを行いました。
-100/3 // -33.33..., 0.3663 millisec
Math.floor(-100/3) // -34, 0.5016 millisec
~~(-100/3) // -33, 0.3619 millisec
(-100/3>>0) // -33, 0.3632 millisec
(-100/3|0) // -33, 0.3856 millisec
(-100-(-100%3))/3 // -33, 0.3591 millisec
/* a=-100, b=3 */
a/b // -33.33..., 0.4863 millisec
Math.floor(a/b) // -34, 0.6019 millisec
~~(a/b) // -33, 0.5148 millisec
(a/b>>0) // -33, 0.5048 millisec
(a/b|0) // -33, 0.5078 millisec
(a-(a%b))/b // -33, 0.6649 millisec
上記はそれぞれ1,000万回の試行に基づいています。
結論:((a/b>>0)
または(~~(a/b))
または(a/b|0)
)を使用して、効率を約20%向上させます。また、彼らが持つすべての矛盾していることに注意してくださいMath.floor
、a/b<0 && a%b!=0
。
Math.floor
か。他のAPI関数について、誰がどのように知っているか、または~
(ビットごとではない)演算子について学び、JSでビットごとの演算がどのように機能するかを学習してから、二重チルドの影響を理解しますか?
Math.floor
よりよく理解するでしょう。そして、そうでなくても、これはグーグルです。
ES6では新しいMath.trunc
方法が導入されています。これにより、@ MarkElliotの回答を修正して、負の数でも機能するようにすることができます。
var div = Math.trunc(y/x);
var rem = y % x;
注ことMath
の方法は、彼らが2の上に数字で動作することをビット演算子を上回る利点持っている31。
18014398509481984 == 18014398509481985
。
~~(x/y)
ます。署名された最大54ビットまでのより大きな数をサポートする必要がありますか?使用Math.trunc
あなたがそれを持っている場合、またはMath.floor
それ以外の場合は(正しい負の数の場合)。さらに大きな数をサポートする必要がありますか?大きなライブラリを使用してください。
divmod
、次のようなそれを実装することができますfunction divmod(x, y) { var div = Math.trunc(x/y); var rem = x % y; return [div, rem]; }
var remainder = x % y;
return (x - remainder) / y;
Math.trunc
:) を使用するメソッドと同じ値を返します。100,3で確認しました。-100,3; 100、-3および-100、-3。もちろん、あなたのコメントや物事が変わってからかなりの時間が経過しました。
私は通常使用します:
const quotient = (a - a % b) / b;
const remainder = a % b;
それはおそらく最もエレガントではありませんが、動作します。
関数parseInt
を使用して、切り捨てられた結果を取得できます。
parseInt(a/b)
剰余を取得するには、mod演算子を使用します。
a%b
parseIntには、基数10で基数パラメータを使用しないようにするために、文字列に関するいくつかの落とし穴があります
parseInt("09", 10)
場合によっては、数値の文字列表現が科学表記になることがあります。この場合、parseIntは誤った結果を生成します。
parseInt(100000000000000000000000000000000, 10) // 1e+32
この呼び出しは結果として1を生成します。
parseInt
可能な場合は避けてください。ダグラスクロックフォードの警告は次のとおりです。「文字列の最初の文字が0の場合、文字列は10進数ではなく8進数で評価されます。8、8、9は数字ではないため、parseInt( "08")とparseInt ( "09")は結果として0を生成します。このエラーは、日付と時刻を解析するプログラムで問題を引き起こします。幸い、parseIntは基数パラメーターを取ることができるため、parseInt( "08"、10)は8を生成します。基数パラメータを指定してください。」 archive.oreilly.com/pub/a/javascript/excerpts/...
parseInt
避けるべきだとは言っていません。注意すべきいくつかの落とし穴があります。これらのことを認識し、対処する準備をしておく必要があります。
parseInt
数値引数を指定して呼び出さないでください。parseInt
数値を切り捨てるのではなく、部分的に数値の文字列を解析することになっています。
JavaScriptは、それらの数学的定義に従って、負の数の下限と残りの非整数の数を正しく計算します。
FLOORは「パラメーターよりも小さい最大の整数」として定義されるため、次のようになります。
REMAINDERは、除算の "残り"(ユークリッド算術)として定義されます。被除数が整数でない場合、商も通常整数ではありません。つまり、余りはありませんが、商が整数になるように強制される場合(そして、誰かが剰余または剰余を取得しようとすると、それが起こります)浮動小数点数)、非整数の「残り」があることは明らかです。
JavaScriptはすべてを期待どおりに計算するので、プログラマーは適切な質問をするように注意する必要があります(そして、人々は質問に答えるように注意する必要があります!)Yarinの最初の質問は「XのYによる整数除算とは何か」ではありませんでしたが、代わりに、「与えられた整数の完全な回数が別の整数になります」。整数の除算(除数による除数)は、数値(除数)が別の(被除数)に「入る」時間よりも-1小さいため、正の数の場合、答えは両方とも同じですが、負の数の場合は異なります。つまり、FLOORは負の数の整数除算に対して正しい答えを返しますが、Yarinはそれを要求しませんでした。
gammaxは正しく答えました。そのコードはYarinからの質問どおりに機能します。一方、サミュエルは間違っている、彼は数学をしなかったと思う、または彼はそれがうまくいくのを見たであろう(また、彼は彼の例の除数が何であるかを言っていなかったが、私はそれが3):
残り= X%Y = -100%3 = -1
GoesInto =(X-残り)/ Y =(-100--1)/ 3 = -99 / 3 = -33
ちなみに、Firefox 27.0.1でコードをテストしましたが、正数と負数、および非整数値を使用して、被除数と除数の両方で期待どおりに機能しました。例:
-100.34 / 3.57:GoesInto = -28、Remainder = -0.3800000000000079
はい、気づきました。精度の問題がありますが、確認する時間がありませんでした(Firefox、Windows 7、または私のCPUのFPUの問題かどうかはわかりません)。ただし、整数のみが関係するYarinの質問の場合、gammaxのコードは完全に機能します。
アレックスムーアニエミ回答としてののコメント:
ここでGoogleからRubyを検索divmod
する場合、次のように実装できます。
function divmod(x, y) {
var div = Math.trunc(x/y);
var rem = x % y;
return [div, rem];
}
結果:
// [2, 33]
divmod
床除算(Math.floor
)を使用しますMath.trunc
。これは、NPM divmod
パッケージ、Rubydivmod
、SWI-Prologdivmod
、およびおそらく他の多くの実装にも当てはまります。
divmod
2つの操作を別々に計算するよりも2倍速く実行されるため、通常は存在することに注意してください。このパフォーマンス上の利点なしにそのような関数を提供することは混乱するかもしれません。
2のべき乗で除算する場合は、ビットごとの演算子を使用できます。
export function divideBy2(num) {
return [num >> 1, num & 1];
}
export function divideBy4(num) {
return [num >> 2, num & 3];
}
export function divideBy8(num) {
return [num >> 3, num & 7];
}
(1つ目は商、2つ目は余りです)
function divideByPowerOf2(num, exponent) { return [num >> exponent, num & ((1 << exponent) - 1)]; }
。
これは常にゼロに向かって切り捨てられます。手遅れかどうかはわかりませんが、次のようになります。
function intdiv(dividend, divisor) {
divisor = divisor - divisor % 1;
if (divisor == 0) throw new Error("division by zero");
dividend = dividend - dividend % 1;
var rem = dividend % divisor;
return {
remainder: rem,
quotient: (dividend - rem) / divisor
};
}
JSランタイムがそのように表すことができない非常に大きな整数の余りを計算する必要がある場合(2 ^ 32より大きい整数は浮動小数点として表されるため、精度が失われます)、いくつかのトリックを実行する必要があります。
これは、日常生活の多くの場合に存在するチェックデジットの多くのケース(銀行口座番号、クレジットカードなど)をチェックする場合に特に重要です。
まず第一にあなたはあなたの数を文字列として必要とします(そうでなければあなたはすでに精度を失っており、残りは意味がありません)。
str = '123456789123456789123456789'
ここで、文字列を小さな部分に分割する必要があります。残りの部分と文字列の一部を連結して9桁に収まるように、十分に小さくします。
digits = 9 - String(divisor).length
文字列を分割する正規表現を準備する
splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')
たとえば、digits
7の場合、正規表現は
/.{1,7}(?=(.{7})+$)/g
これは、最大長7の空でない部分文字列に一致し、その後に続きます((?=...)
に7の倍数の文字数正の先読み)。 'g'は、最初の一致で停止するのではなく、式をすべての文字列で実行します。
次に、各部分を整数に変換し、reduce
(前の剰余を加算して-または0-正しい10の累乗を掛けて)剰余を計算します。
reducer = (rem, piece) => (rem * Math.pow(10, digits) + piece) % divisor
これは、「減算」剰余アルゴリズムのために機能します。
n mod d = (n - kd) mod d
これにより、最終的な剰余に影響を与えることなく、数値の小数表現の「最初の部分」をその剰余で置き換えることができます。
最終的なコードは次のようになります。
function remainder(num, div) {
const digits = 9 - String(div).length;
const splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g');
const mult = Math.pow(10, digits);
const reducer = (rem, piece) => (rem * mult + piece) % div;
return str.match(splitter).map(Number).reduce(reducer, 0);
}
3.5 % 2
1.5と評価されます。必要に応じて(parseInt、floorなど)を処理するようにしてください