2012-03-26 16 views
9

अनुप्रयोग विकास टीम दृष्टिकोण से 99 99 99 * 99 99 99 (परिणाम> Integer.MAX_VALUE) जैसे इंटीजर ओवरफ्लो से निपटने के लिए सामान्य प्रथा क्या है?सामान्य अभ्यास इंटीजर ओवरफ्लो से कैसे निपटें?

कोई भी BigInt अनिवार्य कर सकता है और Integer के उपयोग को प्रतिबंधित कर सकता है, लेकिन क्या यह एक अच्छा/बुरा विचार है?

उत्तर

13

यदि यह अत्यंत महत्वपूर्ण है कि पूर्णांक अतिप्रवाह नहीं है, आप अपने खुद के अतिप्रवाह को पकड़ने के संचालन, जैसे परिभाषित कर सकते हैं:

def +?+(i: Int, j: Int) = { 
    val ans = i.toLong + j.toLong 
    if (ans < Int.MinValue || ans > Int.MaxValue) { 
    throw new ArithmeticException("Int out of bounds") 
    } 
    ans.toInt 
} 

आप इस चालू करने के लिए समृद्ध-your-पुस्तकालय पैटर्न का उपयोग करने में सक्षम हो सकता है ऑपरेटरों में; यदि JVM ठीक से भागने का विश्लेषण कर प्रबंधन करता है, आप इसके लिए एक दंड का बहुत अधिक मिल जाएगा नहीं:

class SafePlusInt(i: Int) { 
    def +?+(j: Int) = { /* as before, except without i param */ } 
} 
implicit def int_can_be_safe(i: Int) = new SafePlusInt(i) 

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

scala> 1000000000 +?+ 1000000000 
res0: Int = 2000000000 

scala> 2000000000 +?+ 2000000000 
java.lang.ArithmeticException: Int out of bounds 
    at SafePlusInt.$plus$qmark$plus(<console>:12) 
    ... 

यदि यह अत्यंत महत्वपूर्ण नहीं है, तो मानक इकाई परीक्षण और कोड समीक्षा और इस तरह के मामलों के बड़े बहुमत में समस्या को पकड़ना चाहिए। BigInt का उपयोग करना संभव है, लेकिन 100 या उससे अधिक के कारक द्वारा आपके अंकगणितीय को धीमा कर देगा, और जब आपको मौजूदा विधि का उपयोग करना होगा, तो Int लेना होगा।

+0

हाय रेक्स, तत्काल उत्तर के लिए धन्यवाद! एक उचित समाधान हालांकि इसे कुछ पुन: फैक्टरिंग की आवश्यकता हो सकती है। जटिल प्रकार प्रणाली पर विचार करने वाले मानक "ऑपरेटर" कार्यों में ओवर-फ्लो चेक फ्लैग जोड़ने वाले इंटीजर बेस क्लास के साथ छेड़छाड़ करना कितना कठिन होगा? – IODEV

+0

बीटीडब्ल्यू, "+? +" "के संबंध में, क्या मानक स्केल नामकरण रूपांतरण का उपयोग करना चाहिए?/अग्रिम धन्यवाद – IODEV

+0

@IODEV - आप एक रैपर वर्ग जोड़ सकते हैं, लेकिन आप बेस क्लास के साथ समझदारी से छेड़छाड़ नहीं कर सकते क्योंकि यह वास्तव में जेवीएम में 'int' आदिम को मानचित्र करता है और इसलिए इसमें बहुत से विशेष कंपाइलर जादू हैं। '?' की पसंद मेरे द्वारा arbitary था; '+' से शुरू होने से ऑपरेटर की प्राथमिकता समान रहेगी, और मुझे समरूपता पसंद है (और अन्य पर्याप्त करते हैं ताकि जब मैं इसे _convention_ नहीं कहूंगा तो यह कम से कम परिचित है), इसलिए मैंने अंत में एक और '+' जोड़ा । '+ @ 'भी काम करेगा। –

4

अब तक का सबसे आम पूर्णांक अतिप्रवाह के बारे में अभ्यास है कि प्रोग्रामर को पता है कि इस मुद्दे को, मौजूद है मामलों में जहां वे हो सकता है के लिए देखने के लिए, और उचित जाँच करता है बनाने के लिए या पुन: व्यवस्थित गणित ताकि जीता overflows उम्मीद कर रहे हैं है ऐसा नहीं होता है, (ए * बी)/सी के बजाए * (बी/सी) करने जैसी चीज़ें। यदि परियोजना इकाई परीक्षण का उपयोग करती है, तो वे मामलों को शामिल करने के लिए ओवरफ्लो को लागू करने और मजबूर करने के लिए शामिल करेंगे।

मैंने कभी भी उस टीम से कोड पर काम नहीं किया है या उससे अधिक की आवश्यकता है, इसलिए मैं कहूंगा कि लगभग सभी सॉफ्टवेयर के लिए यह काफी अच्छा है।

एक एम्बेडेड एप्लिकेशन मैंने देखा है कि वास्तव में, ईमानदार-से-स्पेगेटी-राक्षस को ओवरफ्लो को रोकने के लिए आवश्यक है, उन्होंने यह साबित करके यह किया कि प्रत्येक पंक्ति में अतिप्रवाह संभव नहीं था, ऐसा लगता है कि ऐसा हो सकता है।

def naturals[A](implicit f: Integral[A]) = 
    Stream.iterate(f.one)(f.plus(_, f.one)) 

तुम भी कर सकते हैं:

+3

अंडरफ्लो उतना ही खराब हो सकता है, जो 'ए * (बी/सी)' आपको दे सकता है। आम तौर पर '((ए * बी) .toLong/c) .toInt' या' डबल' के बराबर करना चाहिए। –

+0

ओवरफ्लो के साथ, प्रोग्रामर के लिए संभावना के बारे में जागरूक होने और अपने जुडमेंट का उपयोग करने के लिए अंडरफ्लो से निपटने का तरीका है। अपने तर्कों को विस्तृत करना और फिर जब भी आप गणित करते हैं तो नतीजे को संकुचित करते हैं, प्रदर्शन और कोड पठनीयता के लिए बुरी चीजें होती हैं, और उन मामलों में काम नहीं करती है जहां अंतिम परिणाम खत्म होता है या नीचे आती है। – mjfgates

+0

निर्भर करता है कि कोड कितना प्रदर्शन-महत्वपूर्ण है। मनमाना-परिशुद्धता पूर्णांक के साथ बहुत कम प्रदर्शन प्राप्त कर सकते हैं। बढ़ते प्रदर्शन को चौड़ा/संकीर्ण करने के साथ मिल सकता है। उच्च प्रदर्शन प्रोग्रामर को यह समझने की आवश्यकता है कि मूल्यों को इतनी चौड़ी/संकीर्ण करने की अनुमति क्यों नहीं है। अगर आप पूरी तरह से विभाजन से बच सकते हैं, तो अल्ट्रा-उच्च प्रदर्शन सबसे अच्छा होगा। –

6

आप स्काला उपयोग कर रहे हैं (और टैग मैं आप कर रहे हैं यह सोचते कर रहा हूँ के आधार पर), एक बहुत सामान्य समाधान scala.math.Integral प्रकार वर्ग के खिलाफ अपने पुस्तकालय कोड लिखना है अच्छे वाक्य रचना के लिए संदर्भ सीमा और Integral.Implicits का उपयोग करें:

import scala.math.Integral.Implicits._ 

def squares[A: Integral] = naturals.map(n => n * n) 

अब आप या तो Int या Long या BigInt की जरूरत के रूप में के साथ इन तरीकों का उपयोग कर सकतेके उदाहरण के बाद सेउन सभी के लिए मौजूद हैं:

scala> squares[Int].take(10).toList 
res0: List[Int] = List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100) 

scala> squares[Long].take(10).toList 
res0: List[Long] = List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100) 

scala> squares[BigInt].take(10).toList 
res1: List[BigInt] = List(1, 4, 9, 16, 25, 36, 49, 64, 81, 100) 

कोई ज़रूरत नहीं पुस्तकालय कोड बदलने के लिए: बस का उपयोग Long या BigInt ओवरफ़्लो चिंता और Int अन्यथा है।

आप प्रदर्शन के मामले में कुछ जुर्माना अदा करेंगे, लेकिन सामान्यता और Int -or- BigInt को स्थगित करने की क्षमता इसके लायक हो सकती है।

+0

'लांग' का उपयोग करके हमारे पास ओवरफ्लो समस्या फिर से है। परिवर्तनीय को मापने की इकाई को बांधने के लिए – Jus12

3

सरल मानसिकता के अलावा, जैसा कि @mjfgates द्वारा नोट किया गया है, वहां कुछ अभ्यास हैं जो मैं हमेशा स्केल किए गए-दशमलव (गैर-फ़्लोटिंग-पॉइंट) वास्तविक दुनिया की मात्रा से निपटने के दौरान उपयोग करता हूं। यह आपके विशेष आवेदन के लिए बिंदु पर नहीं हो सकता है - अगर अग्रिम में माफी माँगती है।

सबसे पहले, यदि उपयोग में माप की कई इकाइयां हैं, तो मूल्यों को हमेशा स्पष्ट रूप से पहचानना चाहिए कि वे क्या हैं। यह सम्मेलन नामकरण, या माप की प्रत्येक इकाई के लिए एक अलग वर्ग का उपयोग करके किया जा सकता है। मैंने हमेशा नामों का उपयोग किया है - हर चर नाम पर एक प्रत्यय। errors from confusion over the units को समाप्त करने के अलावा, यह अतिप्रवाह के बारे में सोचने को प्रोत्साहित करता है क्योंकि उपायों को केवल संख्याओं के रूप में सोचा जाने की संभावना कम होती है।

दूसरा, अतिप्रवाह चिंता का मेरा सबसे लगातार स्रोत आम तौर पर एक माप से दूसरे में परिवर्तित होता है - जब इसे बहुत महत्वपूर्ण अंक की आवश्यकता होती है। उदाहरण के लिए, सेमी से इंच तक रूपांतरण कारक 0.3 93700787402 है। महत्वपूर्ण अंक के अतिप्रवाह और हानि से बचने के लिए, आपको सही क्रम में गुणा करने और विभाजित करने के लिए सावधान रहना होगा। मैं इस एक लंबे समय में नहीं किया है, लेकिन मेरा मानना ​​है कि आप क्या चाहते हैं की तरह कुछ:

Rational.scala में जोड़े, पुस्तक से:

def rescale(i:Int) : Int = { 
     (i * (numer/denom)) + (i/denom * (numer % denom)) 

तो फिर तुम के रूप में परिणाम (एक specs2 से छोटा मिल परीक्षण):

val InchesToCm = new Rational(1000000000,393700787) 
    InchesToCm.rescale(393700787) must_== 1000000000 
    InchesToCm.rescale(1) must_== 2 

यह नकारात्मक स्केलिंग कारकों के दौर में नहीं है, या सौदा नहीं करता है। एक उत्पादन कार्यान्वयन numer/denom और numer % denom को कारक बनाना चाहता है।

+0

+1। अगर मैं "चरित्र गणना" और "बाइट गिनती" को मिश्रित करने की कोशिश करता हूं तो मुझे कोड चिल्लाता है, जब मैं भयानक डीबीसीएस-टू-यूनिकोड रूपांतरणों के ढेर के साथ सामना कर रहा था, तो एक साल मेरे बेकन को बचाया। – mjfgates

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

  • कोई संबंधित समस्या नहीं^_^