2012-09-01 16 views
24

संभव डुप्लिकेट:
How can I check if multiplying two numbers in Java will cause an overflow?जावा कोड में पूर्णांक ओवरफ़्लो को कैसे रोकें?

मान लीजिए मैं एक जावा वर्ग विधि है, जो * और + संचालन का उपयोग करता है।

 
int foo(int a, int b) { 
    ... // some calculations with + and * 
} 

यह सुनिश्चित करने के लिए कि foo में कोई ओवरफ़्लो नहीं होता है?

मुझे लगता है मैं BigDecimal उपयोग कर सकते हैं या बदलने के सभी + और की तरह "रैपर" के साथ *:

 
int sum(int a, int b) { 
    int c = a + b; 
    if (a > 0 && b > 0 && c < 0) 
    throw new MyOverfowException(a, b) 
    return c; 
} 

int prod(int a, int b) { 
    int c = a * b; 
    if (a > 0 && b > 0 && c < 0) 
    throw new MyOverfowException(a, b) 
    return c; 
} 

वहाँ सुनिश्चित करें कि कोई int अतिप्रवाह एक जावा विधि में होता है बनाने के लिए बेहतर तरीके हैं?

+3

आप क्यों जांचते हैं कि यह शून्य से नीचे है या नहीं? एक int 0 से नीचे अच्छी तरह से जा सकता है। – 11684

+0

सटीक होने के लिए, यह एक int की सीमा है: -2,147,483,648 से 2,147,483,647 – 11684

+0

आप मूल्यों को क्लैंप करना चाहते हैं? –

उत्तर

17

इंजीनियरिंग परिप्रेक्ष्य से यह एक कठिन समस्या है।

Secure Coding साइट की सिफारिश की: पूर्व शर्त के

  • उपयोग; यानी इनपुट को रेंज-चेक करें ताकि ओवरफ्लो असंभव हो,
  • अगले बड़े आदिम पूर्णांक प्रकार का उपयोग करके प्रत्येक अंकगणितीय ऑपरेशन कर रहा है और स्पष्ट रूप से अतिप्रवाह, या
  • बिगइंटर का उपयोग करके जांच कर रहा है।

यह Dr Dobbs article आदिम अंकगणित तरीकों कि एक स्पष्ट अतिप्रवाह चेक के साथ प्रत्येक आदिम आपरेशन कर का एक पुस्तकालय बनाने का सुझाव देते हैं। (आप इसे ऊपर बुलेट प्वाइंट # 2 के कार्यान्वयन के रूप में देख सकते हैं।) लेकिन लेखकों ने सुझाव दिया है कि आप अंकगणित बाइटकोड को प्रतिस्थापित करने के लिए बाइटकोड रीराइटिंग का उपयोग करते हैं, जिसमें ओवरफ्लो चेक शामिल करने वाले समकक्ष विधियों को कॉल किया जाता है।

दुर्भाग्यवश, जावा में ओवरफ़्लो जांच को मूल रूप से सक्षम करने का कोई तरीका नहीं है।(लेकिन यह कई अन्य भाषाओं में लागू होता है, उदाहरण के लिए सी, सी ++ ...)

+0

उनमें से दूसरा वह है जो मेरा उत्तर – Alnitak

+1

करता है "इंजीनियरिंग परिप्रेक्ष्य से यह एक कठिन समस्या है।" - यह मुश्किल नहीं है: प्रत्येक ऑपरेशन के बाद अतिप्रवाह रजिस्टर ध्वज की जांच करने के लिए बस मशीन कोड उत्पन्न करें। यही सी # "चेक" ब्लॉक करता है। मुद्दा यह है कि जावा इसे एक विकल्प के रूप में पेश नहीं करता है, क्योंकि यह मनुष्य की बुद्धि से परे नहीं है। – Rich

+0

@Rich - यदि आप जावा कंपाइलर को संशोधित करने की स्थिति में नहीं हैं तो यह मुश्किल है। ज्यादातर लोग नहीं हैं! –

5

योग: जांच करें कि बी अधिकतम मूल्य के अंतर से बड़ा है जो आप int minus में स्टोर कर सकते हैं। यदि कोई और/या बी नकारात्मक हो सकता है, तो आपको (i) सावधान रहना चाहिए कि पहले से ही अंतर जांच के लिए ओवरफ़्लो न प्राप्त करें और (ii) न्यूनतम के लिए समान जांच करें।

उत्पाद: अधिक कठिन है। मैं पूर्णांक को दो आधा-लंबाई पूर्णांक में विभाजित करता हूं (यानी यदि int 32 बिट है, तो इसे बिट-मास्किंग और स्थानांतरण का उपयोग करके दो 16 बिट संख्याओं में विभाजित करें)। फिर गुणा करें, और फिर देखें कि परिणाम 32 बिट में फिट बैठता है या नहीं।

इस शर्त के तहत सब कुछ कि आप अस्थायी परिणाम के लिए long लेना नहीं चाहते हैं।

20

ओवरफ्लो की जांच करने का एक तरीका है ऑपरेटरों को बड़े प्रकार (मूल ऑपरेंड बिट लंबाई की दोगुनी) के लिए प्रचारित करना है, फिर ऑपरेशन करें, और फिर देखें कि परिणामी मान मूल प्रकार के लिए बहुत बड़ा है, जैसे

int sum(int a, int b) { 
    long r = (long)a + b; 
    if (r >>> 32 != 0) { // no sign extension 
     throw new MyOverflowException(a, b); 
    } 
    return (int)r; 
} 

यदि आपका मूल प्रकार एक long है, तो आप है कि बड़े प्रकार के रूप में BigInteger उपयोग करने के लिए होगा।

+0

मुझे पता है कि यह उत्तर पुराना है, लेकिन इस समाधान को काम करने की गारंटी नहीं है क्योंकि बड़े प्रकार के बड़े पैमाने पर ओवरफ्लो हो सकते हैं और छोटे प्रकार के लिए सामान्य दिखाई देने वाली सीमा में समाप्त हो सकते हैं। – yitzih

+0

@yitzih आप गलत हैं - दो (सकारात्मक) पूर्णांक के अतिरिक्त लंबे समय तक ऑपरेंड की तुलना में 1 बिट से अधिक मूल्य के मूल्य से अधिक नहीं हो सकता है। प्रश्न के बाधाओं को "बड़े प्रकार के स्वयं के अतिप्रवाह" के साथ समाप्त करने का कोई तरीका नहीं है – Alnitak

+0

@yitzihI मैं भूल गया कि गुणा भी शामिल है, लेकिन वहां भी, दो 31 बिट सकारात्मक पूर्णांक का उत्पाद 62 बिट्स से अधिक नहीं हो सकता है। – Alnitak

3

मान लीजिए कि ए और बी सकारात्मक या नकारात्मक दोनों हैं, और यदि ए + बी का संकेत ए के संकेत के बराबर नहीं है और बी, तो अतिप्रवाह होता है। आप इस नियम का उपयोग यह तय करने के लिए कर सकते हैं कि अतिप्रवाह होता है और अपवाद फेंकता है या नहीं। जब आप इस एक्सपर्टियन को पकड़ते हैं, तो आप इसे पिछले उत्तरों में मेटाइऑन विधि के अनुसार सौदा कर सकते हैं। एक और तरीका है कि सबसे बड़ा रेंज प्रकार का उपयोग करके ऑपरेशन करना है जो ओवरफ्लो नहीं होगा। आप इंटीग्रर्स के बीच ऑपरेशन के लिए लंबे समय तक उपयोग कर सकते हैं।

संबंधित मुद्दे