नकारात्मक संख्या के साथ मोडुलो ऑपरेशन


192

एक सी कार्यक्रम में मैं नीचे दिए गए ऑपरेशनों की कोशिश कर रहा था (बस व्यवहार की जांच करने के लिए)

 x = 5 % (-3);
 y = (-5) % (3);
 z = (-5) % (-3); 

printf("%d ,%d ,%d", x, y, z); 

मुझे (2, -2 , -2)gcc के रूप में आउटपुट दिया । मैं हर बार सकारात्मक परिणाम की उम्मीद कर रहा था। क्या एक मापांक नकारात्मक हो सकता है? क्या कोई इस व्यवहार की व्याख्या कर सकता है?


के संभावित डुप्लिकेट stackoverflow.com/questions/4003232/...
जेम्स

जवाबों:


168

C99 के लिए आवश्यक है कि कब a/bप्रतिनिधित्व योग्य हो:

(a/b) * b + a%b बराबर होगाa

यह समझ में आता है, तार्किक रूप से। सही?

आइए देखें कि इससे क्या होता है:


उदाहरण ए 5/(-3)है-1

=> (-1) * (-3) + 5%(-3) =5

यह तभी हो सकता है जब 5%(-3)2 हो।


उदाहरण बी (-5)/3है-1

=> (-1) * 3 + (-5)%3 =-5

ऐसा होने पर ही हो सकता (-5)%3है-2


1
क्या कंपाइलर पर्याप्त स्मार्ट होना चाहिए और पता लगाना चाहिए कि एक अहस्ताक्षरित एक और अहस्ताक्षरित हमेशा सकारात्मक है? वर्तमान में (अच्छी तरह से, जीसीसी 5.2) संकलक को लगता है कि "%" इस मामले में एक "int" देता है, बजाय "अहस्ताक्षरित" यहां तक ​​कि जब दोनों ऑपरेंड uint32_t या उससे बड़े होते हैं।
फ्रेडरिक नॉर्ड

@FrederickNord क्या आपके पास उस व्यवहार को दिखाने के लिए एक उदाहरण है ?
chux -

10
समझें कि आप जो वर्णन करते हैं वह सामान्य int (a / b) (truncate) mod का वर्णन है। लेकिन यह भी संभव है कि नियम फर्श (ए / बी) (नुथ) है। नथ मामले -5/3में -2और मॉड बन जाता है। 1. संक्षेप में: एक मॉड्यूल में एक संकेत होता है जो लाभांश चिह्न (ट्रंकट) का अनुसरण करता है, दूसरे मॉड्यूल में एक संकेत होता है जो विभाजक चिह्न (नथ) का अनुसरण करता है।
इसहाक

1
यह सी मानक का मामला है जो मैं नहीं चाहता। मैं कभी भी शून्य या नकारात्मक मोडुलो संख्याओं के लिए अलग नहीं करना चाहता था, लेकिन अक्सर विपरीत चाहता हूं और सी के आसपास काम करने की आवश्यकता होती है
जो

142

%सी में ऑपरेटर नहीं है सापेक्ष ऑपरेटर लेकिन शेष के ऑपरेटर।

मोडुलो और शेष ऑपरेटर नकारात्मक मूल्यों के संबंध में भिन्न हैं।

एक शेष ऑपरेटर के साथ, परिणाम का संकेत लाभांश के संकेत के समान है, जबकि एक मोडुलो ऑपरेटर के साथ परिणाम का संकेत भाजक के समान है।

सी %ऑपरेशन को परिभाषित करता है a % b:

  a == (a / b * b) + a % b

साथ /की दिशा में काट-छांट के साथ पूर्णांक विभाजन 0। यही ट्रंकेशन है जो 0(और नकारात्मक नकारात्मकता की ओर नहीं) है जो %एक मॉडुलो ऑपरेटर के बजाय एक शेष ऑपरेटर के रूप में परिभाषित करता है ।


8
रेमिनेडर परिभाषा के अनुसार मोडुलो ऑपरेशन का परिणाम है । शेष संचालक जैसी कोई चीज नहीं होनी चाहिए क्योंकि शेष संचालन जैसी कोई चीज नहीं है, इसे मोडुलो कहा जाता है।
गोनोस्तज

41
@gronostaj सीएस में नहीं। हस्केल या स्कीम जैसी उच्च स्तरीय भाषाओं को देखें कि दोनों दो अलग-अलग ऑपरेटरों को परिभाषित करते हैं ( remainderऔर moduloस्कीम में, remऔर modहास्केल में)। ये ऑपरेटर विनिर्देश इन भाषाओं पर भिन्न होते हैं कि विभाजन कैसे किया जाता है: 0 की ओर या नकारात्मक अनंत की ओर छंटनी। वैसे C Standard कभी %भी modulo ऑपरेटर को कॉल नहीं करता है , वे बस इसे % ऑपरेटर नाम देते हैं ।
ahउउह

2
सी में remainder फ़ंक्शन के साथ भ्रमित न होने के लिए , जो आईईईई को विभाग में गोल-गोल-निकटतम निकटतम शब्दार्थ के साथ लागू करता है
एरिक

67

C99 विनिर्देश के आधार पर: a == (a / b) * b + a % b

हम गणना करने के लिए एक फ़ंक्शन लिख सकते हैं (a % b) == a - (a / b) * b!

int remainder(int a, int b)
{
    return a - (a / b) * b;
}

मोडुलो ऑपरेशन के लिए, हमारे पास निम्नलिखित कार्य (मान सकते हैं b > 0)

int mod(int a, int b)
{
    int r = a % b;
    return r < 0 ? r + b : r;
}

मेरा निष्कर्ष यह है कि a % bसी एक शेष ऑपरेशन है और मॉडुलो ऑपरेशन नहीं है।


3
यह bनकारात्मक होने पर सकारात्मक परिणाम नहीं देता है (और वास्तव में rऔर इसके लिए bदोनों नकारात्मक परिणाम कम से कम देता है -b)। उन सभी सूचनाओं के सकारात्मक परिणाम सुनिश्चित करने के लिए जिनका आप उपयोग कर सकते हैं r + abs(b)या bसाइन इन से मिलान करने के लिए आप r*b < 0इसके बजाय स्थिति को बदल सकते हैं ।
मार्टिन एंडर

@MartinEnder r + abs(b)यूबी है जब b == INT_MIN
chux -

60

मुझे नहीं लगता कि संख्या नकारात्मक होने की जाँच करने की कोई आवश्यकता नहीं है।

सकारात्मक मोड्यूलो को खोजने का एक सरल कार्य यह होगा -

संपादित करें: मान लें N > 0औरN + N - 1 <= INT_MAX

int modulo(int x,int N){
    return (x % N + N) %N;
}

यह x के सकारात्मक और नकारात्मक दोनों मानों के लिए काम करेगा ।

मूल PS: जैसा कि @chux द्वारा बताया गया है, यदि आपका x और N क्रमशः INT_MAX-1 और INT_MAX जैसी किसी चीज़ तक पहुंच सकता है, तो बस इसके intसाथ बदलें long long int

और यदि वे लंबे समय की सीमाओं को पार कर रहे हैं (जैसे कि LLONG_MAX के पास), तो आप सकारात्मक और नकारात्मक मामलों को अलग से संभालेंगे, जैसा कि यहां अन्य उत्तरों में वर्णित है।


1
ध्यान दें कि जब N < 0, परिणाम के रूप में नकारात्मक हो सकता है modulo(7, -3) --> -2। साथ ही गणित x % N + Nको ओवरफ्लो कर सकता है intजो अपरिभाषित व्यवहार है। उदाहरण modulo(INT_MAX - 1,INT_MAX)-3 में परिणाम हो सकता है।
chux -

हां, उस स्थिति में आप केवल long long intनकारात्मक मामले को अलग-अलग उपयोग कर सकते हैं या संभाल सकते हैं (सादगी खोने की कीमत पर)।
उदयराज देशमुख

9

अन्य उत्तर C99 या बाद में बताए गए हैं , पूर्णांकों का विभाजन जिसमें नकारात्मक संचालक शामिल होते हैं, हमेशा शून्य की ओर बढ़ते हैं

ध्यान दें कि, C89 में , चाहे परिणाम गोल या नीचे की ओर हो, कार्यान्वयन-परिभाषित है। क्योंकि सभी मानकों में (a/b) * b + a%bसमान aहै, %नकारात्मक ऑपरेंड को शामिल करने का परिणाम C89 में कार्यान्वयन-परिभाषित भी है।


5

क्या एक मापांक नकारात्मक हो सकता है?

%नकारात्मक हो सकता है क्योंकि यह शेष ऑपरेटर है , विभाजन के बाद शेष है, यूक्लिडियन_डिविजन के बाद नहीं । C99 के बाद से परिणाम 0, नकारात्मक या सकारात्मक हो सकता है।

 // a % b
 7 %  3 -->  1  
 7 % -3 -->  1  
-7 %  3 --> -1  
-7 % -3 --> -1  

सापेक्ष ओ पी चाहता था एक क्लासिक है इयूक्लिडियन सापेक्ष , नहीं %

मैं हर बार सकारात्मक परिणाम की उम्मीद कर रहा था।

एक यूक्लिडियन मोडुलो निष्पादित करने के लिए जो अच्छी तरह से परिभाषित है जब भी a/bपरिभाषित किया जाता है, a,bकिसी भी संकेत के होते हैं और परिणाम कभी भी नकारात्मक नहीं होता है:

int modulo_Euclidean(int a, int b) {
  int m = a % b;
  if (m < 0) {
    // m += (b < 0) ? -b : b; // avoid this form: it is UB when b == INT_MIN
    m = (b < 0) ? m - b : m + b;
  }
  return m;
}

modulo_Euclidean( 7,  3) -->  1  
modulo_Euclidean( 7, -3) -->  1  
modulo_Euclidean(-7,  3) -->  2  
modulo_Euclidean(-7, -3) -->  2   

2

मोडुलो ऑपरेशन का परिणाम संख्यात्मक के संकेत पर निर्भर करता है, और इस प्रकार आप y और z के लिए -2 प्राप्त कर रहे हैं

यहाँ संदर्भ है

http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_14.html

इंटेगर डिवीजन

यह खंड पूर्णांक विभाजन करने के लिए कार्यों का वर्णन करता है। ये कार्य GNU C लाइब्रेरी में निरर्थक हैं, क्योंकि GNU C में '/' ऑपरेटर हमेशा शून्य की ओर गोल होता है। लेकिन अन्य सी कार्यान्वयन में, नकारात्मक तर्क के साथ '/' अलग-अलग दौर कर सकते हैं। div और ldiv उपयोगी हैं क्योंकि वे निर्दिष्ट करते हैं कि कैसे भागफल को गोल करें: शून्य की ओर। शेष में अंश के समान चिन्ह है।


5
आप एएनएसआई सी के बारे में एक पाठ का उल्लेख कर रहे हैं। यह सी का एक काफी पुराना मानदंड है। निश्चित नहीं है कि पाठ एएनएसआई सी के संबंध में सही है, लेकिन निश्चित रूप से सी 99 के संबंध में नहीं है। C99 में C6.5.5 पूर्णांक विभाजन को हमेशा शून्य की ओर झुका हुआ परिभाषित किया जाता है।
पैलेक

2

गणित में, जहाँ ये परंपराएँ उपजी हैं, वहाँ कोई धारणा नहीं है कि मोडुलो अंकगणित को सकारात्मक परिणाम देना चाहिए।

उदाहरण के लिए।

1 मॉड 5 = 1, लेकिन यह -4 के बराबर भी हो सकता है। यही है, 1/5 से 0 या -4 से एक शेष 1 प्राप्त होता है (5 के दोनों कारक)

इसी तरह, -1 मॉड 5 = -1, लेकिन यह 4 के बराबर भी हो सकता है, यानी -1/5 उपज शेष -1 से 0 या 4 से -5 है। (5 के दोनों कारक)

आगे पढ़ने के लिए गणित में समतुल्यता वर्ग देखें


समतुल्यता वर्ग एक अलग अवधारणा है और मोडुलो को बहुत सख्त तरीके से परिभाषित किया गया है। मान लीजिए कि हम दो पूर्णांक संख्या करते हैं aऔर b, b <> 0। यूक्लिडियन डिवीजन प्रमेय के अनुसार पूर्णांक की एक जोड़ी मौजूद है m, rजहां a = m * b + rऔर 0 <= r < abs( b )। कहा r(गणितीय) modulo ऑपरेशन का परिणाम है और परिभाषा के अनुसार गैर नकारात्मक है। अधिक पढ़ने और विकिपीडिया पर आगे के लिंक: en.wikipedia.org/wiki/Euclidean_division
Ister

यह सच नहीं है। 1 mod 5हमेशा 1 -4 mod 5है। 1 भी हो सकता है, लेकिन वे अलग-अलग चीजें हैं।
फेलिपक

2

C99 मानक के अनुसार , खंड 6.5.5 गुणक ऑपरेटर , निम्नलिखित की आवश्यकता है:

(a / b) * b + a % b = a

निष्कर्ष

शेष संचालन के परिणाम का संकेत, C99 के अनुसार, लाभांश के समान है।

आइए कुछ उदाहरण देखें ( dividend / divisor):

जब केवल लाभांश नकारात्मक होता है

(-3 / 2) * 2  +  -3 % 2 = -3

(-3 / 2) * 2 = -2

(-3 % 2) must be -1

जब केवल भाजक नकारात्मक होता है

(3 / -2) * -2  +  3 % -2 = 3

(3 / -2) * -2 = 2

(3 % -2) must be 1

जब विभाजक और लाभांश दोनों नकारात्मक होते हैं

(-3 / -2) * -2  +  -3 % -2 = -3

(-3 / -2) * -2 = -2

(-3 % -2) must be -1

6.5.5 गुणक संचालक

वाक्य - विन्यास

  1. गुणक अभिव्यक्ति:
    • cast-expression
    • multiplicative-expression * cast-expression
    • multiplicative-expression / cast-expression
    • multiplicative-expression % cast-expression

प्रतिबन्ध

  1. प्रत्येक ऑपरेंड में अंकगणित प्रकार होगा। की ऑपरेंड % ऑपरेटर पूर्णांक प्रकार होगा।

शब्दार्थ

  1. सामान्य अंकगणित रूपांतरण ऑपरेंड पर किए जाते हैं।

  2. बाइनरी * ऑपरेटर का परिणाम ऑपरेंड का उत्पाद है।

  3. / ऑपरेटर का परिणाम दूसरे द्वारा पहले ऑपरेंड के विभाजन से भागफल है; % ऑपरेटर का परिणाम शेष है। दोनों ऑपरेशनों में, यदि दूसरे ऑपरेंड का मान शून्य है, तो व्यवहार अपरिभाषित है।

  4. जब पूर्णांकों को विभाजित किया जाता है, तो / ऑपरेटर का परिणाम बीजीय भागफल होता है जिसमें किसी भी आंशिक भाग को छोड़ दिया जाता है [1]। यदि भागफल a/bप्रतिनिधित्व योग्य है, तो अभिव्यक्ति (a/b)*b + a%bसमान होगी a

[१]: इसे अक्सर "शून्य की ओर झुकाव" कहा जाता है।


1

मापांक ऑपरेटर शेष देता है। सी में मापांक ऑपरेटर आमतौर पर अंश का संकेत लेता है

  1. x = 5% (-3) - यहाँ अंश धनात्मक है इसलिए इसका परिणाम 2 है
  2. y = (-5)% (3) - यहाँ अंश ऋणात्मक है इसलिए इसका परिणाम -2 है
  3. z = (-5)% (-3) - यहाँ अंश ऋणात्मक है इसलिए इसका परिणाम २ है

इसके अलावा मापांक (शेष) ऑपरेटर का उपयोग केवल पूर्णांक प्रकार के साथ किया जा सकता है और इसका उपयोग फ्लोटिंग बिंदु के साथ नहीं किया जा सकता है।


2
यह अच्छा होगा यदि आप बाहरी संसाधनों के लिंक के साथ इसका बैकअप ले सकते हैं।
जे ... एस

1

मेरा मानना ​​है कि यह सोचने के लिए अधिक उपयोगी है modक्योंकि यह सार अंकगणित में परिभाषित है; एक ऑपरेशन के रूप में नहीं, बल्कि विभिन्न तत्वों और विभिन्न ऑपरेटरों के साथ अंकगणित के एक पूरे अलग वर्ग के रूप में। इसका मतलब यह है कि इसके अलावा mod 3"सामान्य" जोड़ के समान नहीं है; अर्थात्; पूर्णांक जोड़।

तो जब आप करते हैं:

5 % -3

आप सेट करने के लिए पूर्णांक 5 को एक तत्व में मैप करने का प्रयास कर रहे हैं mod -3। ये तत्व हैं mod -3:

{ 0, -2, -1 }

इसलिए:

0 => 0, 1 => -2, 2 => -1, 3 => 0, 4 => -2, 5 => -1

कहो कि आपको किसी कारण से 30 घंटे तक रहना है, उस दिन आपके पास कितने घंटे शेष होंगे? 30 mod -24

लेकिन सी लागू नहीं है mod, यह एक शेष है। वैसे भी, मुद्दा यह है कि यह नकारात्मक लौटने के लिए समझ में आता है।

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