Volgens Google Calculator(-13) % 64
is 51
.
Volgens Javascript (zie deze JSBin) is het -13
.
Hoe los ik dit op?
Antwoord 1, autoriteit 100%
Number.prototype.mod = function (n) {
return ((this % n) + n) % n;
};
Uit dit artikel: De JavaScript Modulo-bug
Antwoord 2, autoriteit 65%
Het gebruik van Number.prototype
is LANGZAAM, omdat elke keer dat u de prototypemethode gebruikt, uw nummer wordt verpakt in een Object
. In plaats van dit:
Number.prototype.mod = function(n) {
return ((this % n) + n) % n;
}
Gebruik:
function mod(n, m) {
return ((n % m) + m) % m;
}
Zie: http://jsperf.com/negative-modulo/2
~97% sneller dan het gebruik van een prototype. Als prestaties voor jou belangrijk zijn natuurlijk..
Antwoord 3, autoriteit 11%
De %
-operator in JavaScript is de rest-operator, niet de modulo-operator (het belangrijkste verschil is hoe negatieve getallen worden behandeld):
-1 % 8 // -1, not 7
Antwoord 4, autoriteit 6%
Een “mod”-functie om een positief resultaat te retourneren.
var mod = function (n, m) {
var remain = n % m;
return Math.floor(remain >= 0 ? remain : remain + m);
};
mod(5,22) // 5
mod(25,22) // 3
mod(-1,22) // 21
mod(-2,22) // 20
mod(0,22) // 0
mod(-1,22) // 21
mod(-21,22) // 1
En natuurlijk
mod(-13,64) // 51
Antwoord 5, autoriteit 3%
Het geaccepteerde antwoord maakt me een beetje nerveus omdat het de %-operator opnieuw gebruikt. Wat als Javascript het gedrag in de toekomst verandert?
Hier is een tijdelijke oplossing waarbij % niet opnieuw wordt gebruikt:
function mod(a, n) {
return a - (n * Math.floor(a/n));
}
mod(1,64); // 1
mod(63,64); // 63
mod(64,64); // 0
mod(65,64); // 1
mod(0,64); // 0
mod(-1,64); // 63
mod(-13,64); // 51
mod(-63,64); // 1
mod(-64,64); // 0
mod(-65,64); // 63
Antwoord 6, autoriteit 2%
Als x
een geheel getal is en n
een macht van 2 is, kun je x & (n - 1)
in plaats van x % n
.
> -13 & (64 - 1)
51
Antwoord 7
Hoewel het zich niet gedraagt zoals u had verwacht, betekent dit niet dat JavaScript zich niet ‘gedraagt’. Het is een keuze die JavaScript heeft gemaakt voor zijn modulo-berekening. Omdat beide antwoorden per definitie logisch zijn.
Zie ditvan Wikipedia. Je kunt rechts zien hoe verschillende talen het teken van het resultaat hebben gekozen.
Antwoord 8
Dit is geen bug, er zijn 3 functies om modulo te berekenen, je kunt degene gebruiken die aan je behoeften voldoet (ik raad aan om de Euclidische functie te gebruiken)
De decimale deelfunctie afkappen
console.log( 41 % 7 ); // 6
console.log( -41 % 7 ); // -6
console.log( -41 % -7 ); // -6
console.log( 41 % -7 ); // 6
Gehele deelfunctie
Number.prototype.mod = function(n) {
return ((this%n)+n)%n;
};
console.log( parseInt( 41).mod( 7) ); // 6
console.log( parseInt(-41).mod( 7) ); // 1
console.log( parseInt(-41).mod(-7) ); // -6
console.log( parseInt( 41).mod(-7) ); // -1
Euclidische functie
Number.prototype.mod = function(n) {
var m = ((this%n)+n)%n;
return m < 0 ? m + Math.abs(n) : m;
};
console.log( parseInt( 41).mod( 7) ); // 6
console.log( parseInt(-41).mod( 7) ); // 1
console.log( parseInt(-41).mod(-7) ); // 1
console.log( parseInt( 41).mod(-7) ); // 6
Antwoord 9
Dus het lijkt erop dat als je probeert om graden te modificeren (zodat als je -50 graden – 200 graden hebt), je zoiets wilt gebruiken als:
function modrad(m) {
return ((((180+m) % 360) + 360) % 360)-180;
}
Antwoord 10
Ik heb ook te maken met negatieve a en negatieve n
//best perf, hard to read
function modul3(a,n){
r = a/n | 0 ;
if(a < 0){
r += n < 0 ? 1 : -1
}
return a - n * r
}
// shorter code
function modul(a,n){
return a%n + (a < 0 && Math.abs(n));
}
//beetween perf and small code
function modul(a,n){
return a - n * Math[n > 0 ? 'floor' : 'ceil'](a/n);
}
Antwoord 11
Er is een NPM-pakket dat het werk voor u doet. Je kunt het installeren met het volgende commando.
npm install just-modulo --save
Gebruik gekopieerd van de README
import modulo from 'just-modulo';
modulo(7, 5); // 2
modulo(17, 23); // 17
modulo(16.2, 3.8); // 17
modulo(5.8, 3.4); //2.4
modulo(4, 0); // 4
modulo(-7, 5); // 3
modulo(-2, 15); // 13
modulo(-5.8, 3.4); // 1
modulo(12, -1); // NaN
modulo(-3, -8); // NaN
modulo(12, 'apple'); // NaN
modulo('bee', 9); // NaN
modulo(null, undefined); // NaN
GitHub-repository is te vinden via de volgende link:
https://github.com/angus-c /just/tree/master/packages/number-modulo
Antwoord 12
Voor de lol, hier is een “wrap”-functie die een beetje als een modulo werkt, behalve dat je ook de minimumwaarde van het bereik kunt specificeren (in plaats van dat het 0 is):
const wrap = (value = 0, min = 0, max = 10) =>
((((value - min) % (max - min)) + (max - min)) % (max - min)) + min;
Eigenlijk gewoon de echte modulo-formule, compenseert het zodanig dat min
eindigt op 0, en voegt daarna min
weer toe.
Handig als je een waarde hebt die je tussen twee waarden wilt houden.