जावास्क्रिप्ट% (मोडुलो) नकारात्मक संख्याओं के लिए एक नकारात्मक परिणाम देता है


252

इसके अनुसार Google के कैलकुलेटर (-13) % 64 है 51

जावास्क्रिप्ट के अनुसार (इसे देखें JSBin ) यह है -13

मैं यह कैसे तय करुं?


यह सिर्फ एक मिसाल हो सकती है। क्या आपका मतलब है (-13) % 64या -(13 % 64)? निजी तौर पर, मैं अतिरिक्त स्पष्टता के लिए, दोनों तरह से पार्न्स में रखूँगा।
MatrixFrog

2
अनिवार्य रूप से डुप्लिकेट कैसे जावा नकारात्मक संख्याओं के साथ माप गणना करता है? हालांकि यह एक जावास्क्रिप्ट सवाल है।
राष्ट्रपति जेम्स के। पोल्

85
जावास्क्रिप्ट कभी कभी एक बहुत क्रूर मजाक की तरह लगता है
ड्यूकफैगिंग

6
गूगल गलत नहीं किया जा सकता
caub

10
जेएस में मौलिक समस्या %मॉडुलो ऑपरेटर नहीं है। यह शेष ऑपरेटर है। जावास्क्रिप्ट में कोई मॉडुलो ऑपरेटर नहीं है। तो स्वीकृत उत्तर जाने का मार्ग है।
रेडू

जवाबों:


262
Number.prototype.mod = function(n) {
    return ((this%n)+n)%n;
};

इस लेख से लिया गया: जावास्क्रिप्ट मोडुलो बग


23
मुझे नहीं पता कि मैं इसे "बग" कहूंगा। मॉडुलो ऑपरेशन नकारात्मक संख्याओं पर बहुत अच्छी तरह से परिभाषित नहीं है, और विभिन्न कंप्यूटिंग वातावरण इसे अलग तरीके से संभालते हैं। मोडुलो ऑपरेशन पर विकिपीडिया का लेख इसे अच्छी तरह से कवर करता है।
डेनियल प्राइडेन

22
यह गूंगा लग सकता है क्योंकि इसे अक्सर 'मोदुलो' कहा जाता है, यह सुझाव देता है कि यह इसकी गणित की परिभाषा (ℤ / nℤ बीजगणित देखें) के समान व्यवहार करेगा, जो यह नहीं करता है।
एटिने

7
N जोड़ने से पहले मोडुलो क्यों लें? क्यों न केवल एन जोड़ें और फिर मोडुलो लें?
पहुंचे

12
यदि आपने इस% n का उपयोग नहीं किया है तो यह आपके लिए विफल होगा x < -n - जैसे (-7 + 5) % 5 === -2लेकिन ((-7 % 5) + 5) % 5 == 3
21

7
मैं इस उत्तर को जोड़ने की सलाह देता हूं कि इस फ़ंक्शन का उपयोग करने के लिए -13% के बजाय प्रारूप (-13) .mod (10) का उपयोग करना चाहिए। यह अधिक स्पष्ट होगा।
Jp_

161

उपयोग करना Number.prototypeधीमा है, क्योंकि हर बार जब आप प्रोटोटाइप विधि का उपयोग करते हैं तो आपकी संख्या एक में लिपटे रहती है Object। इसके अलावा:

Number.prototype.mod = function(n) {
  return ((this % n) + n) % n;
}

उपयोग:

function mod(n, m) {
  return ((n % m) + m) % m;
}

देख: http://jsperf.com/negative-modulo/2

~ 97% प्रोटोटाइप का उपयोग करने से तेज। यदि प्रदर्शन आप के लिए महत्वपूर्ण है ..


1
महान टिप। मैंने आपके jsperf को लिया और इस प्रश्न के बाकी समाधानों की तुलना में (लेकिन ऐसा लगता है कि यह वैसे भी सबसे अच्छा है): jsperf.com/negative-modulo/3
Mariano Desanze

11
माइक्रो अनुकूलन। आप किसी भी फर्क करने के लिए इसके लिए बड़े पैमाने पर आधुनिक गणना कर रहे होंगे। कोड जो सबसे स्पष्ट और सबसे अधिक रखरखाव योग्य है, उसके बाद प्रदर्शन विश्लेषण का अनुकूलन करें।
क्रिस 13

मुझे लगता है कि आपको अपने दूसरे उदाहरण @StuR में गलत तरीके से अपना nएस और mएस मिला है । यह होना चाहिए return ((n % m) + m) % m;
vimist

यह स्वीकृत उत्तर के लिए टिप्पणी होनी चाहिए, स्वयं के लिए उत्तर नहीं।
xehpuk

5
इस उत्तर में दी गई प्रेरणा एक सूक्ष्म अनुकूलन है, हाँ, लेकिन प्रोटोटाइप को संशोधित करना समस्याग्रस्त है। सबसे कम दुष्प्रभावों के साथ दृष्टिकोण को प्राथमिकता दें, जो यह एक है।
कीन

30

%जावास्क्रिप्ट में ऑपरेटर शेष ऑपरेटर, नहीं सापेक्ष ऑपरेटर (मुख्य अंतर यह है कि कैसे ऋणात्मक संख्याओं इलाज कर रहे हैं में किया जा रहा है):

-1 % 8 // -1, not 7


8
यह चाहिए शेष ऑपरेटर के नाम से जाना है, लेकिन यह है : मापांक ऑपरेटर कहा जाता developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/...
बिग McLargeHuge

15
@DaveKennedy: MDN एक आधिकारिक भाषा संदर्भ नहीं है, यह एक समुदाय-संपादित साइट है जो कभी-कभी गलत हो जाती है। युक्ति इसे मॉडुलो ऑपरेटर नहीं कहती है, और जहां तक ​​मैं बता सकता हूं कि यह कभी नहीं है (मैं ईएस 3 में वापस चला गया)। यह स्पष्ट रूप से कहता है कि ऑपरेटर एक निहित विभाजन के शेष पैदावार देता है, और बस इसे "% ऑपरेटर" कहता है।
टीजे क्राउडर

2
यदि इसे कहा जाता है remainder, तो यह परिभाषा से 0 से बड़ा होना चाहिए। आप हाई स्कूल से विभाजन प्रमेय याद नहीं कर सकते हैं ?! तो शायद आप यहाँ देख सकते हैं: en.wikipedia.org/wiki/Euclidean_division
अहमद

19

सकारात्मक परिणाम वापस करने के लिए एक "मॉड" फ़ंक्शन।

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

और निश्चित रूप से

mod(-13,64) // 51

1
एमडीएन एक आधिकारिक भाषा संदर्भ नहीं है, यह एक समुदाय-संपादित साइट है जो कभी-कभी गलत हो जाती है। युक्ति इसे मॉडुलो ऑपरेटर नहीं कहती है, और जहां तक ​​मैं बता सकता हूं कि यह कभी नहीं है (मैं ईएस 3 में वापस चला गया)। यह स्पष्ट रूप से कहता है कि ऑपरेटर एक निहित विभाजन के शेष पैदावार देता है, और बस इसे "% ऑपरेटर" कहता है।
टीजे क्राउडर

1
उफ़, आपके द्वारा निर्दिष्ट लिंक वास्तव #sec-applying-the-mod-operatorमें url में ही संदर्भित है :) वैसे भी, नोट के लिए धन्यवाद, मैंने अपने उत्तर से फ़्लफ़ लिया, यह वास्तव में वैसे भी महत्वपूर्ण नहीं है।
शनीमल

3
@ शनिमल: LOL! ऐसा होता है। HTML संपादक द्वारा एक त्रुटि। कल्पना पाठ नहीं करता है।
टीजे क्राउडर

10

स्वीकृत उत्तर मुझे थोड़ा परेशान करता है क्योंकि यह% ऑपरेटर का फिर से उपयोग करता है। क्या होगा अगर जावास्क्रिप्ट भविष्य में व्यवहार को बदलता है?

यहां एक समाधान है जो% का पुन: उपयोग नहीं करता है:

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

8
यदि जावास्क्रिप्ट ने गणितीय परिभाषा से मेल खाने के लिए modulo ऑपरेटर को बदल दिया, तो स्वीकृत उत्तर अभी भी काम करेगा।
घूर

20
"क्या होगा अगर जावास्क्रिप्ट भविष्य में व्यवहार को बदल दे?" - क्यों होगा? ऐसे मौलिक ऑपरेटर के व्यवहार को बदलने की संभावना नहीं है।
nnnnnn

1
+1 इस चिंता के लिए और वैकल्पिक उत्तर को # उत्तर -4467559 और 4 कारणों से वैकल्पिक रूप से साझा करने के लिए : (1) यह क्यों बताता है, और हाँ "इस तरह के मौलिक ऑप के व्यवहार को बदलने की संभावना नहीं है" लेकिन फिर भी विचार करने के लिए विवेकपूर्ण यहां तक ​​कि खोजने के लिए यह आवश्यक नहीं है। (2) एक टूटे हुए के संदर्भ में एक काम करने वाले ऑप को परिभाषित करते हुए, प्रभावशाली, कम से कम 1 लुक पर चिंताजनक है, कम से कम तिल होना दिखाया जाना चाहिए (3) मैं इस विकल्प को अच्छी तरह से सत्यापित नहीं करता, मुझे आसानी से पता चलता है त्वरित देखो। (4) छोटे: इसमें 2 (mod) divs के बजाय 1 div + 1 mul का उपयोग किया गया है और मैंने MUCH पर पहले सुना है w / oa अच्छा FPU, गुणन तेज था।
भाग्य वास्तुकार

2
@DestinyArchitect यह विवेकपूर्ण नहीं है, यह व्यर्थ है। यदि वे शेष ऑपरेटर के व्यवहार को बदलने के लिए थे, तो इसका उपयोग करके कार्यक्रमों की एक अच्छी श्रृंखला टूट जाएगी। ऐसा कभी होने वाला नहीं है।
तत्कालीन

9
क्या के व्यवहार करता है, तो -, *, /, ;, ., (, ), ,, Math.floor, functionया returnपरिवर्तन? फिर आपका कोड बुरी तरह से टूट गया है।
xehpuk

5

यद्यपि यह आपकी अपेक्षा के अनुरूप व्यवहार नहीं कर रहा है, इसका मतलब यह नहीं है कि जावास्क्रिप्ट 'व्यवहार' नहीं है। यह एक विकल्प है जो जावास्क्रिप्ट अपने मॉडुलो गणना के लिए बनाया गया है। क्योंकि, परिभाषा के अनुसार या तो उत्तर समझ में आता है।

इसे विकिपीडिया से देखें । आप सही पर देख सकते हैं कि विभिन्न भाषाओं ने परिणाम के संकेत को कैसे चुना।


3

यदि xएक पूर्णांक है और n2 की शक्ति है, तो आप x & (n - 1)इसके बजाय उपयोग कर सकते हैं x % n

> -13 & (64 - 1)
51 

2

तो ऐसा लगता है कि यदि आप डिग्रियों को संशोधित करने का प्रयास कर रहे हैं (ताकि यदि आपके पास -50 डिग्री - 200 डिग्री हो), तो आप कुछ का उपयोग करना चाहेंगे:

function modrad(m) {
    return ((((180+m) % 360) + 360) % 360)-180;
}

1

मैं नकारात्मक और नकारात्मक 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); 
    }

1

यह एक बग नहीं है, मोड्यूलो की गणना करने के लिए 3 कार्य हैं, आप अपनी आवश्यकताओं के अनुसार उपयोग कर सकते हैं (मैं यूक्लिडियन फ़ंक्शन का उपयोग करने की सिफारिश करूंगा)

दशमलव भाग फ़ंक्शन को छोटा करना

console.log(  41 %  7 ); //  6
console.log( -41 %  7 ); // -6
console.log( -41 % -7 ); // -6
console.log(  41 % -7 ); //  6

पूर्णांक भाग समारोह

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

यूक्लिडियन फ़ंक्शन

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

1
यूक्लिडियन फंक्शन में चेकिंग m <0 बेकार है क्योंकि ((यह% n) + n)% n हमेशा पॉजिटिव है
bormat

@bormat हां यह है, लेकिन जावास्क्रिप्ट %में नकारात्मक परिणाम लौट सकते हैं (इसे ठीक करने के लिए इन कार्यों का उद्देश्य है)
zessx

आपने यह लिखा था [कोड] Number.prototyp.mod = function (n) {var m = ((यह% n) + n]% n; वापसी एम <0? m + Math.abs (n): एम; }; [/ code] मुझे n का एक मान दीजिए जहाँ m négative है। वे n का कोई मूल्य नहीं हैं जहाँ m négative है क्योंकि आप पहले% के बाद n जोड़ते हैं।
बोरमेट

इस चेक के बिना, parseInt(-41).mod(-7)वापसी होगी -6बजाय 1(और यह वास्तव में पूर्णांक भाग समारोह मैंने लिखा का उद्देश्य है)
zessx

हा ठीक है, आप सही कह रहे हैं, मेरे सभी माफी, मैं नकारात्मक मोडुलो को भूल गया, मैं केवल "इस" नकारात्मक के बारे में सोच रहा था। क्या मैं Math.abs Number.prototype.mod = function (n) {रिटर्न ((यह% n) + Math.abs (n))% n को स्थानांतरित करने का सुझाव दे सकता हूं; }; (-41) .mod (-7) == 1 // कोई ज़रूरत नहीं parseInt
bormat

0

एक एनपीएम पैकेज है जो आपके लिए काम करेगा। आप इसे निम्न आदेश के साथ स्थापित कर सकते हैं।

npm install just-modulo --save

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 रिपॉजिटरी को निम्न लिंक के माध्यम से पाया जा सकता है:

https://github.com/angus-c/just/tree/master/packages/number-modulo

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.