Math.abs Integer.Min_VALUE के लिए गलत मान देता है


90

यह कोड:

System.out.println(Math.abs(Integer.MIN_VALUE));

रिटर्न -2147483648

क्या इसे पूर्ण मान के रूप में वापस नहीं करना चाहिए 2147483648?

जवाबों:


102

Integer.MIN_VALUEहै -2147483648, लेकिन एक 32 बिट पूर्णांक शामिल कर सकते हैं उच्चतम मूल्य है +2147483647+2147483648प्रभावी ढंग से "रोल ओवर" करने के लिए एक 32 बिट इंट में प्रतिनिधित्व करने का प्रयास किया जाएगा -2147483648। इसका कारण यह है कि जब हस्ताक्षर किए गए पूर्णांक का उपयोग करते हैं, तो दो के पूरक द्विआधारी प्रतिनिधित्व होते हैं +2147483648और -2147483648समान होते हैं। यह एक समस्या नहीं है, हालांकि, जैसा +2147483648कि सीमा से बाहर माना जाता है।

इस मामले पर थोड़ा और पढ़ने के लिए, आप दो के पूरक पर विकिपीडिया लेख देखना चाह सकते हैं ।


6
खैर, कोई समस्या प्रभाव को कम नहीं कर रही है, यह बहुत अच्छी तरह से समस्याओं का मतलब हो सकता है। व्यक्तिगत रूप से मेरे पास एक अपवाद या संख्या प्रणाली होगी जो उच्च स्तर की भाषा में गतिशील रूप से बढ़ती है।
मार्टन बॉड्यूज

40

आपके द्वारा इंगित किया गया व्यवहार वास्तव में, काउंटर-सहज ज्ञान युक्त है। हालाँकि, यह व्यवहार javadocMath.abs(int) द्वारा निर्दिष्ट एक है :

यदि तर्क नकारात्मक नहीं है, तो तर्क लौटाया जाता है। यदि तर्क नकारात्मक है, तो तर्क का निषेध लौटा दिया जाता है।

अर्थात्, Math.abs(int)निम्न जावा कोड की तरह व्यवहार करना चाहिए:

public static int abs(int x){
    if (x >= 0) {
        return x;
    }
    return -x;
}

यही कारण है, नकारात्मक मामले में, है -x

जेएलएस सेक्शन 15.15.4 के अनुसार , इसके -xबराबर है (~x)+1, जहां ~बिटवाइज़ पूरक ऑपरेटर है।

यह जाँचने के लिए कि क्या यह सही लगता है, आइए उदाहरण के तौर पर -1 लें

पूर्णांक मान -1को 0xFFFFFFFFजावा में हेक्साडेसिमल के रूप में नोट किया जा सकता है (इसे printlnया किसी अन्य विधि से देखें)। -(-1)इस प्रकार लेना देता है:

-(-1) = (~(0xFFFFFFFF)) + 1 = 0x00000000 + 1 = 0x00000001 = 1

तो, यह काम करता है।

आइए अब हम कोशिश करते हैं Integer.MIN_VALUE। यह जानकर कि सबसे कम पूर्णांक का प्रतिनिधित्व किया जा सकता है 0x80000000, अर्थात् , 1 को पहला सेट और 0 को सेट किए गए 31 शेष बिट्स हैं:

-(Integer.MIN_VALUE) = (~(0x80000000)) + 1 = 0x7FFFFFFF + 1 
                     = 0x80000000 = Integer.MIN_VALUE

और यही कारण है कि Math.abs(Integer.MIN_VALUE)रिटर्न Integer.MIN_VALUE। यह भी ध्यान रखें कि 0x7FFFFFFFहै Integer.MAX_VALUE

उस ने कहा, हम भविष्य में इस प्रति-सहज रिटर्न मूल्य के कारण समस्याओं से कैसे बच सकते हैं?

  • हम @Bombe द्वारा बताया गया था , हमारे intएस को longपहले कास्ट कर सकते थे। हालांकि, हमें भी होना चाहिए

    • उन्हें वापस intएस में डाल दिया , जो काम नहीं करता है क्योंकि Integer.MIN_VALUE == (int) Math.abs((long)Integer.MIN_VALUE)
    • या longकिसी भी तरह से उम्मीद करना जारी रखें कि हम कभी भी Math.abs(long)एक मूल्य के बराबर कॉल नहीं करेंगे Long.MIN_VALUE, क्योंकि हमारे पास भी है Math.abs(Long.MIN_VALUE) == Long.MIN_VALUE
  • हम BigIntegerहर जगह एस का उपयोग कर सकते हैं , क्योंकि BigInteger.abs()वास्तव में हमेशा सकारात्मक मूल्य वापस आता है। यह एक अच्छा विकल्प है, हालांकि कच्चे पूर्णांक प्रकारों में हेरफेर करने की तुलना में थोड़ा धीमा है।

  • हम Math.abs(int)इस तरह के लिए अपने स्वयं के आवरण लिख सकते हैं :

/**
 * Fail-fast wrapper for {@link Math#abs(int)}
 * @param x
 * @return the absolute value of x
 * @throws ArithmeticException when a negative value would have been returned by {@link Math#abs(int)}
 */
public static int abs(int x) throws ArithmeticException {
    if (x == Integer.MIN_VALUE) {
        // fail instead of returning Integer.MAX_VALUE
        // to prevent the occurrence of incorrect results in later computations
        throw new ArithmeticException("Math.abs(Integer.MIN_VALUE)");
    }
    return Math.abs(x);
}
  • एक पूर्णांक बिटवाइज़ का उपयोग करें और उच्च बिट स्पष्ट करने के लिए, सुनिश्चित करना है कि परिणाम गैर नकारात्मक है: int positive = value & Integer.MAX_VALUE(अनिवार्य रूप से बह निकला Integer.MAX_VALUEकरने 0के बजाय Integer.MIN_VALUE)

अंतिम नोट के रूप में, यह समस्या कुछ समय के लिए जानी जाती है। उदाहरण के लिए देखें इसी प्रविष्टि के बारे में खोज नियम


12

यहाँ जावा जावा डॉक्टर के लिए क्या कहता है ( javadoc में) :

ध्यान दें कि यदि तर्क Integer.MIN_VALUE के मान के बराबर है, तो सबसे नकारात्मक प्रतिनिधित्व योग्य int मान है, परिणाम वही मूल्य है, जो नकारात्मक है।


4

नतीजा यह है कि आप उम्मीद कर रहे हैं, कलाकारों को देखने के लिए Integer.MIN_VALUEकरने के लिए long:

System.out.println(Math.abs((long) Integer.MIN_VALUE));

1
एक संभावित फिक्स, वास्तव में! हालांकि, यह इस तथ्य को हल नहीं करता है कि Math.absएक नकारात्मक संख्या को लौटाने के लिए Math.abs(Long.MIN_VALUE) == Long.MIN_VALUE
प्रतिसंतुलित

1
@bernardpaulus, अच्छा, इसे फेंकने के अलावा क्या करना चाहिए ArithmeticException? इसके अलावा, व्यवहार एपीआई दस्तावेज में स्पष्ट रूप से प्रलेखित है।
बॉम्बे

आपके प्रश्न का कोई अच्छा उत्तर नहीं है ... मैं केवल यह बताना चाहता था कि यह व्यवहार, जो बग का एक स्रोत है, के उपयोग से तय नहीं है Math.abs(long)। मैं यहां अपनी गलती के लिए माफी मांगता हूं: मैंने कहा था कि आपने Math.abs(long)एक फिक्स के रूप में उपयोग का प्रस्ताव रखा था , जब आपने "यह देखने के लिए एक सरल तरीका के रूप में दिखाया था कि परिणाम पूछने वाला उम्मीद कर रहा है"। माफ़ करना।
बर्नार्ड पौलस

जावा 15 में नए तरीकों के साथ वास्तव में एक अपवाद है।
चिपरोर्टिज़

1

2147483648 को जावा में पूर्णांक में संग्रहीत नहीं किया जा सकता है, इसका द्विआधारी प्रतिनिधित्व -2147483648 है।


0

लेकिन (int) 2147483648L == -2147483648 एक नकारात्मक संख्या है जिसका कोई सकारात्मक समकक्ष नहीं है इसलिए इसके लिए सकारात्मक मूल्य नहीं है। आपको Long.MAX_VALUE के साथ समान व्यवहार दिखाई देगा।


0

इसमें एक निश्चितता है जावा 15 इंट और लॉन्ग की विधि होगी। वे कक्षाओं पर मौजूद रहेंगे

java.lang.Math and java.lang.StrictMath

विधियों।

public static int absExact(int a)
public static long absExact(long a)

अगर तुम पास हो जाओ

Integer.MIN_VALUE

या

Long.MIN_VALUE

एक अपवाद फेंक दिया जाता है।

https://bugs.openjdk.java.net/browse/JDK-8241805

मैं यह देखना चाहूंगा कि क्या Long.MIN_VALUE या Integer.MIN_VALUE पास है या नहीं, एक सकारात्मक मूल्य वापस आएगा और अपवाद नहीं।


-1

Math.abs बड़ी संख्याओं के साथ हर समय काम नहीं करता है मैं इस छोटे कोड तर्क का उपयोग करता हूं जो मैंने सीखा था जब मैं 7 साल का था!

if(Num < 0){
  Num = -(Num);
} 

sयहाँ क्या है ?
18.03 को aioobe

क्षमा करें मैं अपने मूल कोड
डेव

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