जावा के मापांक बनाने का सबसे अच्छा तरीका यह है कि इसे नकारात्मक संख्याओं के साथ करना चाहिए?


103

जावा में जब आप करते हैं

a % b

यदि कोई ऋणात्मक है, तो उसे नकारात्मक परिणाम वापस करना होगा, बजाय इसके कि चारों ओर b को लपेटना चाहिए। इसे ठीक करने का सबसे अच्छा तरीका क्या है? केवल एक तरीका है जो मैं सोच सकता हूं

a < 0 ? b + a : a % b

12
नकारात्मक संख्याओं से निपटने के दौरान कोई "सही" मापांक व्यवहार नहीं है - बहुत सारी भाषाएं इस तरह से करती हैं, बहुत सारी भाषाएं इसे अलग करती हैं, और कुछ भाषाएं पूरी तरह से कुछ अलग करती हैं। कम से कम पहले दो में उनके पेशेवरों और विपक्ष हैं।

4
यह मेरे लिए सिर्फ अजीब है। मैंने सोचा कि अगर नकारात्मक होना चाहिए तो केवल नकारात्मक लौटना चाहिए।
fent


2
यह है। लेकिन उस सवाल का शीर्षक बदला जाना चाहिए। मैं उस सवाल पर क्लिक नहीं करता अगर मैं इसे खोज रहा था क्योंकि मुझे पहले से ही पता है कि जावा मॉडुलस कैसे काम करता है।
फेंट

4
मैंने इसका नाम बदलकर "क्यों -13% 64 = 51 है?" से रखा, जो कभी भी एक मिलियन वर्षों में ऐसा कुछ नहीं होगा जिस पर कोई खोज करेगा। तो यह प्रश्न शीर्षक बहुत बेहतर है, और मापांक, नकारात्मक, गणना, संख्या जैसे कीवर्ड पर अधिक खोजा जा सकता है।
एरिक रॉबर्टसन

जवाबों:


144

यह व्यवहार करता है क्योंकि इसे% b = a - a / b * b होना चाहिए; अर्थात यह शेष है।

आप कर सकते हैं (एक% b + b)% b


यह अभिव्यक्ति के परिणाम के रूप में काम करता है (a % b)जरूरी तुलना में कम है b, कोई फर्क नहीं पड़ता अगर aसकारात्मक या नकारात्मक है। जोड़ना bनकारात्मक मूल्यों का ध्यान रखता है a, क्योंकि (a % b)एक नकारात्मक मूल्य है -bऔर 0, (a % b + b)आवश्यक रूप से कम bऔर सकारात्मक है। पिछले मोडुलो के aसाथ शुरू होने के मामले में सकारात्मक था, अगर aसकारात्मक है तो (a % b + b)इससे बड़ा हो जाएगा b। इसलिए, (a % b + b) % bइसे bफिर से छोटे में बदल देता है (और नकारात्मक aमूल्यों को प्रभावित नहीं करता है )।


3
यह बेहतर काम करता है धन्यवाद। और यह ऋणात्मक संख्याओं के लिए काम करता है जो कि b से भी बहुत बड़ा है।
fent

6
यह तब से काम करता है जब परिणाम (a % b)आवश्यक रूप से कम होता है b(कोई फर्क नहीं पड़ता कि aसकारात्मक या नकारात्मक है), जोड़ना bनकारात्मक मूल्यों का ख्याल रखता है a, चूंकि (a % b)कम से कम है bऔर तुलना में कम है 0, (a % b + b)आवश्यक रूप से कम bऔर सकारात्मक है। पिछले मोडुलो के aसाथ शुरू होने के मामले में सकारात्मक था, अगर aसकारात्मक है तो (a % b + b)इससे बड़ा हो जाएगा b। इसलिए, (a % b + b) % bइसे bफिर से छोटे में बदल देता है (और नकारात्मक aमूल्यों को प्रभावित नहीं करता है )।
एथानफर

1
@eitanfar मैंने आपके उत्कृष्ट विवरण को उत्तर में शामिल किया है (एक मामूली सुधार के लिए a < 0, शायद आप एक नज़र डाल सकते हैं)
Maarten Bodewes

5
मैंने अभी इसी विषय पर एक अन्य प्रश्न पर टिप्पणी की है; यह ध्यान देने योग्य हो सकता है कि (a % b + b) % bबहुत बड़े मूल्यों के लिए टूट जाता है aऔर b। उदाहरण के लिए, परिणाम के रूप में उपयोग करना a = Integer.MAX_VALUE - 1और b = Integer.MAX_VALUEदेना होगा -3, जो एक नकारात्मक संख्या है, जो कि आप बचना चाहते थे।
थोरबियर

2
whileयदि आप वास्तव में इसकी आवश्यकता है सिवाय इसके कि आप ifवास्तव में तेजी से केवल एक मामले में जरूरत है, तो @Mikepote धीमा होगा ।
पीटर लॉरी

92

Java 8 के अनुसार, आप Math.floorMod (int x, int y) और Math.floorMod (long x, long y) का उपयोग कर सकते हैं । ये दोनों विधियां पीटर के जवाब के समान परिणाम देती हैं।

Math.floorMod( 2,  3) =  2
Math.floorMod(-2,  3) =  1
Math.floorMod( 2, -3) = -1
Math.floorMod(-2, -3) = -2

1
जावा 8+ के लिए सर्वश्रेष्ठ उत्तर
चरनी काये

कूल, उस एक के बारे में नहीं जानता था। Java 8 ने निश्चित रूप से कुछ PITA का निर्धारण किया है।
फ्रांज डी।

4
अच्छा रास्ता। लेकिन दुर्भाग्य से floatया doubleतर्क के साथ काम नहीं करता है। मॉड बाइनरी ऑपरेटर ( %) भी floatऔर doubleऑपरेंड के साथ काम करता है।
मीर-इस्माइली

11

जावा 8 का उपयोग नहीं करने (या उपयोग करने में सक्षम नहीं) के लिए अभी तक, अमरूद 11.0 के बाद से उपलब्ध IntMath.mod () के साथ बचाव में आया था ।

IntMath.mod( 2, 3) = 2
IntMath.mod(-2, 3) = 1

एक चेतावनी: जावा 8 के Math.floorMod () के विपरीत, विभाजक (दूसरा पैरामीटर) नकारात्मक नहीं हो सकता।


7

संख्या सिद्धांत में, परिणाम हमेशा सकारात्मक होता है। मुझे लगता है कि यह हमेशा कंप्यूटर भाषाओं में ऐसा नहीं होता है क्योंकि सभी प्रोग्रामर गणितज्ञ नहीं होते हैं। मेरे दो सेंट, मैं इसे भाषा का डिज़ाइन दोष मानूंगा, लेकिन अब आप इसे बदल नहीं सकते।

= MOD (-4,180) = 176 = MOD (176, 180) = 176

क्योंकि 180 * (-1) + 176 = -4 180 * 0 + 176 = 176 के समान है

यहाँ घड़ी के उदाहरण का उपयोग करते हुए, http://mathworld.wolfram.com/Congruence.html आप अवधि_फॉल_टाइम मॉड साइकिल_-डायमेंशन -45 मिनट नहीं कहेंगे, आप 15 मिनट कहेंगे, भले ही दोनों उत्तर आधार समीकरण को संतुष्ट करते हों।


1
संख्या सिद्धांत में यह हमेशा सकारात्मक नहीं होता है ... वे अनुरूपता कक्षाओं में आते हैं। आप अपने संकेतन प्रयोजनों के लिए उस वर्ग से जो भी उम्मीदवार चुनने के लिए स्वतंत्र हैं, लेकिन विचार यह है कि यह उस वर्ग के सभी के लिए मैप करता है , और यदि इसमें से एक विशिष्ट अन्य उम्मीदवार का उपयोग करने से एक निश्चित समस्या काफी सरल हो जाती है ( उदाहरण के -1बजाय चुनना n-1) तो उस पर है।
BeUndead

2

जावा 8 में है Math.floorMod, लेकिन यह बहुत धीमा है (इसके कार्यान्वयन में कई विभाजन, गुणा और एक सशर्त है)। यह संभव है कि जेवीएम के पास इसके लिए एक आंतरिक अनुकूलित स्टब है, जो इसे काफी गति देगा।

इसके बिना ऐसा करने का सबसे तेज़ तरीका floorModकुछ अन्य उत्तरों की तरह है, लेकिन बिना किसी सशर्त शाखाओं के और केवल एक धीमी गति से %ऑप।

मान लेना सकारात्मक है, और x कुछ भी हो सकता है:

int remainder = (x % n); // may be negative if x is negative
//if remainder is negative, adds n, otherwise adds 0
return ((remainder >> 31) & n) + remainder;

जब परिणाम n = 3:

x | result
----------
-4| 2
-3| 0
-2| 1
-1| 2
 0| 0
 1| 1
 2| 2
 3| 0
 4| 1

यदि आपको सटीक मॉड ऑपरेटर के बीच केवल 0और समान वितरण की आवश्यकता है n-1, और आपका xपास पास नहीं है 0, तो निम्न और भी तेज़ होगा, क्योंकि अधिक अनुदेश स्तर समानता है और धीमी %गणना अन्य के साथ समानांतर में होगी भागों के रूप में वे इसके परिणाम पर निर्भर नहीं करते हैं।

return ((x >> 31) & (n - 1)) + (x % n)

उपरोक्त के लिए परिणाम n = 3:

x | result
----------
-5| 0
-4| 1
-3| 2
-2| 0
-1| 1
 0| 0
 1| 1
 2| 2
 3| 0
 4| 1
 5| 2

यदि इंट की पूरी रेंज में इनपुट यादृच्छिक है, तो दोनों समाधानों का वितरण समान होगा। यदि इनपुट शून्य के पास होता है, n - 1तो बाद के समाधान में बहुत कम परिणाम होंगे ।


1

यहाँ एक विकल्प है:

a < 0 ? b-1 - (-a-1) % b : a % b

यह उस अन्य सूत्र [(एक% b + b)% b] से अधिक तेज़ हो भी सकता है और नहीं भी। अन्य सूत्र के विपरीत, इसमें एक शाखा होती है, लेकिन एक कम मोडुलो ऑपरेशन का उपयोग करता है। शायद एक जीत अगर कंप्यूटर एक <0 का सही अनुमान लगा सकता है।

(संपादित करें: सूत्र फिक्स्ड।)


1
लेकिन मोडुलो ऑपरेशन के लिए एक डिवीजन की आवश्यकता होती है, जो धीमा भी हो सकता है (विशेषकर अगर प्रोसेसर शाखा को लगभग हर समय सही ढंग से अनुमान लगाता है)। तो यह संभवतः बेहतर है।
डेव

@KarstenR। तुम सही हो! मैंने सूत्र तय किया, अब यह ठीक काम करता है (लेकिन दो और घटाव की जरूरत है)।
स्टीफन रीच

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