अपवादों का समर्थन नहीं करने वाली भाषा में शून्य से विभाजन को कैसे संभालें?


62

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

मैं उस बिंदु पर पहुंच गया हूं, जहां मुझे डिवाइड ऑपरेटर को लागू करना है, और मैं सोच रहा हूं कि शून्य त्रुटि से विभाजन को सबसे अच्छा कैसे संभालना है?

मुझे लगता है कि इस मामले को संभालने के लिए केवल तीन संभव तरीके हैं।

  1. 0परिणाम के रूप में त्रुटि और उत्पादन को अनदेखा करें । यदि संभव हो तो एक चेतावनी लॉगिंग।
  2. NaNसंख्या के लिए एक संभावित मान के रूप में जोड़ें , लेकिन यह सवाल उठाता है कि NaNभाषा के अन्य क्षेत्रों में मूल्यों को कैसे संभालना है ।
  3. प्रोग्राम के निष्पादन को समाप्त करें और उपयोगकर्ता को रिपोर्ट करें कि एक गंभीर त्रुटि हुई है।

विकल्प # 1 एकमात्र उचित समाधान लगता है। विकल्प # 3 व्यावहारिक नहीं है क्योंकि इस भाषा का उपयोग तर्क को रात के क्रोन के रूप में चलाने के लिए किया जाएगा।

शून्य त्रुटि से विभाजन को संभालने के लिए मेरे विकल्प क्या हैं, और विकल्प # 1 के साथ जाने के जोखिम क्या हैं।


12
यदि आपने अपवाद समर्थन जोड़ा है और उपयोगकर्ता ने इसे नहीं पकड़ा है तो आपके पास # 3 विकल्प होगा
शाफ़्ट फ्रीक

82
मैं उत्सुक हूँ, आपको एक पूरी नई प्रोग्रामिंग भाषा बनाने के लिए किस तरह की मूर्खता की आवश्यकता होगी? मेरे अनुभव में, कभी बनाया हर भाषा बेकार (डिजाइन में या निष्पादन में, अक्सर दोनों में) है और यह भी प्राप्त करने के लिए अनुचित रूप से बहुत प्रयास ले लिया है कि ज्यादा। पहले अपवाद के लिए कुछ अपवाद हैं, लेकिन दूसरे के लिए नहीं, और जैसा कि वे आसानी से <0.01% मामलों में हैं, वे शायद माप त्रुटियां हैं ;-)

16
@ डायलेन सबसे नई भाषाएं बनाई गई हैं ताकि व्यावसायिक नियमों को लागू करने से अलग किया जा सके। उपयोगकर्ता को यह जानने की आवश्यकता नहीं है reject "Foo"कि इसे कैसे लागू किया गया था, लेकिन बस यह कि यह एक दस्तावेज को अस्वीकार कर देता है यदि इसमें कीवर्ड शामिल है Foo। मैं उन शब्दों का उपयोग करके भाषा को आसान बनाने की कोशिश करता हूं, जिनसे उपयोगकर्ता परिचित है। एक उपयोगकर्ता को अपनी प्रोग्रामिंग भाषा देने से उन्हें तकनीकी कर्मचारियों के आधार पर व्यावसायिक नियमों को जोड़ने का अधिकार है।
रिएक्टगुलर

19
@ मैथ्यू फोसकारिनी। कभी भी, कभी भी, त्रुटि को अनदेखा करें और चुपचाप वापस लौटें 0. जब एक विभाजन करते हैं, तो 0 पूरी तरह से कानूनी मूल्य हो सकता है (किसी कारण से, पावर बेसिक में ऐसी कोई बात है, और यह वास्तव में एक दर्द है)। यदि आप फ़्लोटिंग पॉइंट नंबरों को विभाजित करते हैं, तो नान या इन्फ अच्छा होगा ( क्यों समझने के लिए IEEE 754 पर एक नज़र डालें )। यदि आप पूर्णांक विभाजित करते हैं, तो आप प्रोग्राम को रोक सकते हैं, 0 से विभाजित करें, इसे कभी भी अनुमति नहीं दी जानी चाहिए (अच्छी तरह से, जब तक कि आप एक सच्चे अपवाद प्रणाली को लागू नहीं करना चाहते)।

16
मैं एक मालिकाना, ट्यूरिंग-पूर्ण प्रोग्रामिंग भाषा का औचित्य साबित करने के लिए पर्याप्त रूप से एक व्यापार डोमेन कॉम्प्लेक्स द्वारा चकित और मोहित हूं, लेकिन काफी गलत परिणामों को सहन करने के लिए पर्याप्त है।
मार्क ई। हासे

जवाबों:


98

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

इसके अलावा, आप इस पैटर्न का पूरी तरह से पालन करके सफल नहीं होंगे। जितनी जल्दी या बाद में आप त्रुटि स्थितियों में चलेंगे, जिसे अनदेखा नहीं किया जा सकता है (जैसे मेमोरी से बाहर निकलना या स्टैक ओवरफ़्लो) और आपको वैसे भी प्रोग्राम को समाप्त करने का एक तरीका लागू करना होगा।

विकल्प # 2 (NaN का उपयोग करके) थोड़ा काम होगा, लेकिन उतना नहीं जितना आप सोच सकते हैं। विभिन्न गणनाओं में NaN को कैसे संभालना है IEEE 754 मानक में अच्छी तरह से प्रलेखित किया गया है, इसलिए आप संभवतया वही कर सकते हैं जो आपके दुभाषिया ने लिखी है।

वैसे: गैर-प्रोग्रामर द्वारा प्रयोग की जाने वाली प्रोग्रामिंग भाषा बनाना कुछ ऐसा है जिसे हम 1964 से (डार्टमाउथ बेसिक) करने की कोशिश कर रहे हैं। अब तक, हम असफल रहे हैं। लेकिन अच्छी किस्मत वैसे भी।


14
+1 धन्यवाद। आपने मुझे एक त्रुटि फेंकने के लिए मना लिया, और अब जब मैंने आपका उत्तर पढ़ा तो मुझे समझ नहीं आया कि मैं क्यों झिझक रहा था। PHPमुझ पर बुरा प्रभाव पड़ा है।
रिएक्टगुलर

24
हाँ यह है। जब मैंने आपका प्रश्न पढ़ा, तो मैंने तुरंत सोचा कि गलत आउटपुट उत्पन्न करने और त्रुटियों के सामने ट्रकिंग रखने के लिए यह एक बहुत ही PHP-esque चीज़ थी। अच्छे कारण हैं कि PHP ऐसा करने में अपवाद क्यों है।
जोएल

4
बुनियादी टिप्पणी के लिए +1। मैं NaNशुरुआत की भाषा में उपयोग करने की सलाह नहीं देता , लेकिन सामान्य तौर पर, शानदार जवाब।
रॉस पैटरसन

8
@Joel अगर वह काफी समय तक जीवित रहे, तो दिक्जस्त्र ने शायद कहा होगा "[PHP] का उपयोग मन को अपंग करता है, इसलिए इसका शिक्षण, एक आपराधिक अपराध माना जाना चाहिए।"
रॉस पैटरसन

12
@Ross। "कंप्यूटर विज्ञान में अहंकार को नैनो-

33

1 - त्रुटि को अनदेखा करें और 0परिणाम के रूप में उत्पन्न करें। यदि संभव हो तो एक चेतावनी लॉगिंग।

यह एक अच्छा विचार नहीं है। बिल्कुल भी। लोग इसके आधार पर शुरू करेंगे और क्या आपको इसे ठीक करना चाहिए, आप बहुत सारे कोड तोड़ देंगे।

2 - NaNसंख्या के लिए एक संभावित मान के रूप में जोड़ें , लेकिन यह सवाल उठाता है कि NaNभाषा के अन्य क्षेत्रों में मूल्यों को कैसे संभालना है ।

आपको NaN को अन्य भाषाओं के रनटाइम्स को करने का तरीका संभालना चाहिए: किसी भी आगे की गणना भी NaN और हर तुलना (यहां तक ​​कि NaN == NaN) की पैदावार को गलत बनाती है।

मुझे लगता है कि यह स्वीकार्य है, लेकिन जरूरी नहीं कि यह नए अनुकूल है।

3 - प्रोग्राम के निष्पादन को समाप्त करें और उपयोगकर्ता को रिपोर्ट करें कि एक गंभीर त्रुटि हुई है।

मेरे हिसाब से यह सबसे अच्छा उपाय है। उस जानकारी के साथ हाथ में उपयोगकर्ताओं को संभालने में सक्षम होना चाहिए 0. आपको एक परीक्षण वातावरण प्रदान करना चाहिए, खासकर अगर यह रात में एक बार चलाने का इरादा है।

एक चौथा विकल्प भी है। विभाजन को एक टर्नरी ऑपरेशन बनाते हैं। इन दोनों में से कोई भी काम करेगा:

  • डिव (अंशांकक, भाजक, वैकल्पिक_संपादित करें)
  • डिव (अंशांकक, भाजक, वैकल्पिक_समरणकर्ता)

लेकिन यदि आप बनाते NaN == NaNहैं false, तो आपको एक isNaN()फ़ंक्शन जोड़ना होगा ताकि उपयोगकर्ता NaNएस का पता लगाने में सक्षम हों ।
AJMansfield

2
@AJMansfield: या तो, या लोग इसे स्वयं लागू करते हैं isNan(x) => x != x:। फिर भी, जब आप NaNअपने प्रोग्रामिंग कोड में आ रहे हैं , तो आपको isNaNचेक जोड़ना शुरू नहीं करना चाहिए , बल्कि कारण को ट्रैक करना चाहिए और वहां आवश्यक जांच करना चाहिए। इसलिए NaNपूरी तरह से प्रचार करना जरूरी है ।
back2dos

5
NaNs प्रमुख रूप से प्रति-सहज ज्ञान युक्त हैं। शुरुआत की भाषा में, वे आगमन पर मृत हो जाते हैं।
रॉस पैटरसन

2
@RossPatterson लेकिन एक शुरुआती आसानी से कह सकता है 1/0- आपको इसके साथ कुछ करना होगा। इसके अलावा Infया संभवतः कोई उपयोगी परिणाम नहीं है NaN- ऐसा कुछ जो कार्यक्रम में आगे त्रुटि का प्रचार करेगा। अन्यथा इस बिंदु पर एक त्रुटि के साथ रोकना एकमात्र उपाय है।
मार्क हर्ड

1
विकल्प 4 को एक फ़ंक्शन के आह्वान की अनुमति देकर सुधार किया जा सकता है, जो कि अप्रत्याशित 0 विभाजक से उबरने के लिए जो भी आवश्यक हो, प्रदर्शन कर सकता है।
साइबरफुल

21

अत्यधिक पूर्वाग्रह के साथ चल रहे आवेदन को समाप्त करें। (पर्याप्त डिबग जानकारी प्रदान करते हुए)

फिर अपने उपयोगकर्ताओं को उन स्थितियों की पहचान करने और उन्हें संभालने के लिए शिक्षित करें जहां भाजक शून्य हो सकता है (उपयोगकर्ता ने मान दर्ज किए, आदि)


13

हास्केल में (और स्काला में समान), अपवादों को फेंकने (या अशक्त संदर्भों को लौटाने) के बजाय रैपर प्रकार Maybeऔर Eitherइस्तेमाल किया जा सकता है। साथ Maybeअगर मूल्य उसके पास "खाली" है उपयोगकर्ता परीक्षण करने के लिए एक मौका है, या वह एक डिफ़ॉल्ट मान जब "unwrapping" प्रदान कर सकते हैं। Eitherसमान है, लेकिन एक वस्तु का उपयोग किया जा सकता है (उदाहरण के लिए एक त्रुटि स्ट्रिंग) यदि कोई समस्या है तो उसका वर्णन करना।


1
यह सच है, लेकिन ध्यान दें कि हास्केल इसका उपयोग शून्य से विभाजन के लिए नहीं करता है। इसके बजाय, प्रत्येक हास्केल प्रकार का एक संभावित मूल्य के रूप में "नीचे" होता है। यह इस अर्थ में अशक्त बिंदुओं की तरह नहीं है कि यह एक अभिव्यक्ति का "मूल्य" है जो समाप्त करने में विफल रहता है। आप मूल्य के रूप में गैर-समाप्ति के लिए परीक्षण नहीं कर सकते हैं, लेकिन परिचालन शब्दार्थ में ऐसे मामले जो समाप्त करने में विफल रहते हैं, एक अभिव्यक्ति के अर्थ का हिस्सा हैं। हास्केल में, "नीचे" मान अतिरिक्त त्रुटि-केस परिणाम भी संभालता है जैसे कि error "some message"फ़ंक्शन का मूल्यांकन किया जा रहा है।
स्टीव 314

व्यक्तिगत रूप से, यदि पूरे कार्यक्रम को निरस्त करने के प्रभाव को वैध माना जाता है, तो मुझे नहीं पता कि शुद्ध कोड में अपवाद को फेंकने का प्रभाव क्यों नहीं हो सकता है, लेकिन यह सिर्फ मेरे लिए है - Haskellअपवादों को फेंकने के लिए शुद्ध अभिव्यक्तियों की अनुमति नहीं है।
स्टीव 314

मुझे लगता है कि यह एक अच्छा विचार है क्योंकि एक अपवाद को फेंकने के अलावा, सभी प्रस्तावित विकल्प उपयोगकर्ताओं से संवाद नहीं करते हैं कि उन्होंने गलती की है। मूल विचार यह है कि उपयोगकर्ता प्रोग्राम को दिए गए मूल्य के साथ एक गलती करता है, इसलिए प्रोग्राम को उपयोगकर्ता को यह बताना चाहिए कि उन्होंने गलत इनपुट दिया (फिर उपयोगकर्ता उपाय करने का एक तरीका सोच सकता है)। उपयोगकर्ताओं को उनकी गलती के बारे में बताए बिना, कोई भी समाधान इतना अजीब लगता है।
सूचित

मुझे लगता है कि यह जाने का रास्ता है ... जंग प्रोग्रामिंग भाषा अपने मानक पुस्तकालय में बड़े पैमाने पर इसका उपयोग करती है।
एनोचागाविया

12

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

x = ...
y = ...

if y ≠ 0:
  return x / y    // In this block, y is known to be nonzero.
else:
  return x / y    // This, however, is a compile-time error.

वैकल्पिक रूप से, एक बुद्धिमान मुखर फ़ंक्शन होता है जो आक्रमणकारियों को स्थापित करता है:

x = ...
require x ≠ 0, "Unexpected zero in calculation"
// For the remainder of this scope, x is known to be nonzero.

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

x = ...           // env1 = { x :: int }
y = ...           // env2 = env1 + { y :: int }
if y ≠ 0:         // env3 = env2 + { y ≠ 0 }
  return x / y    // (/) :: (int, int ≠ 0) → int
else:             // env4 = env2 + { y = 0 }
  ...
...               // env5 = env2

इसके अलावा, यह स्वाभाविक रूप से सीमा और nullजाँच करने के लिए फैली हुई है , अगर आपकी भाषा में ऐसी विशेषताएं हैं।


4
नीट विचार, लेकिन इस प्रकार की बाधा का समाधान एनपी-पूर्ण है। जैसे कुछ कल्पना करो def foo(a,b): return a / ord(sha1(b)[0])। स्थैतिक विश्लेषक SHA-1 को उल्टा नहीं कर सकता है। क्लैंग के पास इस प्रकार का स्थैतिक विश्लेषण है और उथले बग को खोजने के लिए यह बहुत अच्छा है लेकिन ऐसे बहुत सारे मामले हैं जो इसे संभाल नहीं सकते हैं।
मार्क ई। हासे

9
यह एनपी-पूर्ण नहीं है, यह असंभव है - लेम्मा को रोकना कहते हैं। हालाँकि, स्थैतिक विश्लेषक को इसे हल करने की आवश्यकता नहीं है, यह सिर्फ इस तरह के एक बयान पर बकवास कर सकता है और आपको एक स्पष्ट अभिकथन या सजावट जोड़ने की आवश्यकता होती है।
MK01

1
@ MK01: दूसरे शब्दों में, विश्लेषण "रूढ़िवादी" है।
जॉन पूर्डी

11

नंबर 1 (निर्बाध शून्य डालें) हमेशा खराब होता है। # 2 (NaN का प्रचार करें) और # 3 (प्रक्रिया को मारना) के बीच का चुनाव संदर्भ पर निर्भर करता है और आदर्श रूप से वैश्विक सेटिंग होना चाहिए, क्योंकि यह Numpy में है।

यदि आप एक बड़ा, एकीकृत गणना कर रहे हैं, तो NaN का प्रचार करना एक बुरा विचार है क्योंकि यह अंततः आपकी पूरी गणना को फैलाएगा और संक्रमित करेगा --- जब आप सुबह परिणाम देखते हैं और देखते हैं कि वे सभी NaN हैं, तो आप ' घ परिणामों को बाहर फेंकना है और फिर से शुरू करना है। यह बेहतर होता अगर कार्यक्रम समाप्त हो जाता, तो आपको आधी रात में एक कॉल मिलता और इसे निर्धारित किया जाता था --- कम से कम बर्बाद घंटों की संख्या के संदर्भ में।

यदि आप बहुत कम, ज्यादातर स्वतंत्र गणना (जैसे नक्शा-कम या शर्मनाक समानांतर गणना) कर रहे हैं, और आप NaNs के कारण उनमें से कुछ प्रतिशत को बेकार कर सकते हैं, तो यह शायद सबसे अच्छा विकल्प है। कार्यक्रम को समाप्त करना और 99% ऐसा न करना जो शून्य से विभाजित और विभाजित होने वाले 1% के खाते में अच्छा और उपयोगी होगा, एक गलती हो सकती है।

एक अन्य विकल्प, NaNs से संबंधित: एक ही IEEE फ़्लोटिंग-पॉइंट विनिर्देशन Inf और -Inf को परिभाषित करता है, और ये NaN की तुलना में अलग तरीके से प्रचारित होते हैं। उदाहरण के लिए, मुझे पूरा यकीन है कि Inf> किसी भी संख्या और - यदि कोई भी संख्या है, तो वह होगा जो आप चाहते थे कि यदि आपका विभाजन शून्य से हुआ हो क्योंकि शून्य केवल एक छोटी संख्या होना चाहिए था। यदि आपके इनपुट गोल हैं और खतना त्रुटि (जैसे हाथ से लिए गए भौतिक माप) से पीड़ित हैं, तो दो बड़ी मात्राओं का अंतर शून्य हो सकता है। विभाजन-दर-शून्य के बिना, आपको कुछ बड़ी संख्या मिल गई होगी, और शायद आपको परवाह नहीं है कि यह कितना बड़ा है। उस स्थिति में, In और Inffectly मान्य परिणाम हैं।

यह औपचारिक रूप से सही भी हो सकता है, --- बस आप विस्तारित दायरे में काम कर रहे हैं।


लेकिन हम यह नहीं बता सकते कि क्या भाजक सकारात्मक या नकारात्मक होने का इरादा था, इसलिए जब-जब वांछित था, तब डिवीजन + का उत्पादन कर सकता था या वीजा प्राप्त कर सकता था।
डैनियल लुबरोव

सही है, आपकी माप त्रुटि + inf और -inf के बीच अंतर करने के लिए बहुत छोटी है। यह सबसे अधिक बारीकी से रीमैन क्षेत्र से मिलता-जुलता है, जिसमें पूरे जटिल विमान को एक अनंत बिंदु (मूल के विपरीत बिंदु) के साथ एक गेंद पर मैप किया जाता है। बहुत बड़ी सकारात्मक संख्याएँ, बहुत बड़ी ऋणात्मक संख्याएँ, और यहाँ तक कि बहुत बड़ी काल्पनिक और जटिल संख्याएँ, सभी एक अनंत बिंदु के करीब हैं। थोड़ी माप की त्रुटि के साथ, आप उन्हें अलग नहीं कर सकते।
जिम पिवार्स्की

यदि आप उस प्रकार की प्रणाली में काम कर रहे हैं, तो आपको + inf और -inf को समतुल्य होने के रूप में पहचानना होगा, जैसे कि आपको अलग-अलग बाइनरी अभ्यावेदन होने के बावजूद +0 और -0 की पहचान करनी है।
जिम पिवार्स्की

8

3. कार्यक्रम के निष्पादन को समाप्त करें और उपयोगकर्ता को रिपोर्ट करें कि एक गंभीर त्रुटि हुई है।

[यह विकल्प] व्यावहारिक नहीं है ...

बेशक यह व्यावहारिक है: यह प्रोग्रामर की जिम्मेदारी है कि वह एक ऐसा प्रोग्राम लिखे जो वास्तव में समझ में आता है। 0 से विभाजित होने का कोई मतलब नहीं है। इसलिए, यदि प्रोग्रामर एक डिवीज़न का प्रदर्शन कर रहा है, तो यह भी उसकी / उसकी जिम्मेदारी है कि पहले से ही यह सत्यापित कर लें कि डिविज़न 0. के बराबर नहीं है। यदि प्रोग्रामर उस सत्यापन की जाँच करने में विफल रहता है, तो उसे उस गलती का जल्द से जल्द एहसास होना चाहिए। संभव है, और (असामान्य) (NaN) या गलत (0) गणना परिणाम बस उस संबंध में मदद नहीं करेगा।

विकल्प 3 में वही होता है जो मैंने आपके लिए सुझाया होगा, btw, सबसे सीधा, ईमानदार और गणितीय रूप से एक होने के लिए।


4

ऐसा लगता है कि वातावरण में त्रुटियों को नजरअंदाज करने के लिए महत्वपूर्ण कार्यों (यानी; "रात्रिकालीन क्रोन") को चलाना मेरे लिए एक बुरा विचार है। इसे एक विशेषता बनाना एक भयानक विचार है। यह विकल्प 1 और 2 को नियमित करता है।

विकल्प 3 एकमात्र स्वीकार्य समाधान है। अपवादों को भाषा का हिस्सा नहीं होना चाहिए, लेकिन वे वास्तविकता का हिस्सा हैं। आपका समाप्ति संदेश त्रुटि के बारे में जितना संभव हो उतना विशिष्ट और जानकारीपूर्ण होना चाहिए।


3

IEEE 754 में वास्तव में आपकी समस्या के लिए एक अच्छी तरह से परिभाषित समाधान है। Http://en.wikipedia.org/wiki/IEEE_floating_point#Exception_handling का उपयोग किए बिना अपवाद हैंडलिंगexceptions

1/0  = Inf
-1/0 = -Inf
0/0  = NaN

इस तरह आपके सभी ऑपरेशन गणितीय रूप से समझ में आते हैं।

\ lim_ {x \ _ 0} 1 / x = Inf

आईईईई 754 के बाद मेरी राय में यह सबसे अधिक समझ में आता है क्योंकि यह सुनिश्चित करता है कि आपकी गणना कंप्यूटर पर होने वाली सही है और आप अन्य प्रोग्रामिंग भाषाओं के व्यवहार के अनुरूप भी हैं।

एकमात्र समस्या यह है कि Inf और NaN आपके परिणामों को दूषित करने वाले हैं और आपके उपयोगकर्ताओं को ठीक से पता नहीं होगा कि समस्या कहाँ से आ रही है। जूलिया जैसी भाषा पर एक नज़र डालें जो यह काफी अच्छा करती है।

julia> 1/0
Inf

julia> -1/0
-Inf

julia> 0/0
NaN

julia> a = [1,1,1] ./ [2,1,0]
3-element Array{Float64,1}:
   0.5
   1.0
 Inf

julia> sum(a)
Inf

julia> a = [1,1,0] ./ [2,1,0]
3-element Array{Float64,1}:
   0.5
   1.0
 NaN

julia> sum(a)
NaN

गणितीय त्रुटियों के माध्यम से विभाजन त्रुटि को सही ढंग से प्रचारित किया जाता है लेकिन अंत में उपयोगकर्ता को यह नहीं पता होता है कि त्रुटि किस ऑपरेशन से उपजी है।

edit:मैंने जिम पिवार्स्की के उत्तर का दूसरा भाग नहीं देखा, जो मूल रूप से मैं ऊपर कह रहा हूं। मेरी गलती।


2

एसक्यूएल, आसानी से गैर-प्रोग्रामर द्वारा सबसे अधिक व्यापक रूप से उपयोग की जाने वाली भाषा, जो भी इसके लायक है, # 3 करता है। एसक्यूएल लिखने वाले गैर-प्रोग्रामर को देखने और सहायता करने के मेरे अनुभव में, यह व्यवहार आम तौर पर अच्छी तरह से समझा जाता है और आसानी से (केस स्टेटमेंट या इस तरह के साथ) के लिए मुआवजा दिया जाता है। यह मदद करता है कि त्रुटि संदेश जो आपको मिलता है वह बहुत सीधा होता है जैसे कि पोस्टग्रैस 9 में आपको "ईआरओआरओआर: डिवीजन बाय जीरो" मिलता है।


2

मुझे लगता है कि समस्या "नौसिखिए उपयोगकर्ताओं पर लक्षित है। -> तो इसके लिए कोई समर्थन नहीं है ..."

आप क्यों सोच रहे हैं कि नौसिखिए उपयोगकर्ताओं के लिए अपवाद हैंडलिंग समस्याग्रस्त है?

क्या बुरा है? एक "मुश्किल" सुविधा है या पता नहीं क्यों कुछ हुआ है? क्या अधिक भ्रमित कर सकता है? एक कोर डंप या "घातक त्रुटि: शून्य से विभाजित" के साथ एक दुर्घटना?

इसके बजाय, मुझे लगता है कि महान संदेश त्रुटियों के लिए लक्ष्य के लिए एफएआर बेहतर है। तो बजाय कार्य करें: ", बुरा गणना विभाजित 0/0" (यानी: हमेशा डेटा है कि समस्या ही नहीं, कारण दिखाने तरह समस्या का)। PostgreSql संदेश त्रुटियों को कैसे देखते हैं, यह महान IMHO है।

हालाँकि, आप अपवादों के साथ काम करने के अन्य तरीकों को देख सकते हैं जैसे:

http://dlang.org/exception-safe.html

मेरा भी एक भाषा बनाने का सपना है, और इस मामले में मुझे लगता है कि सामान्य अपवादों के साथ एक शायद / वैकल्पिक मिश्रण सबसे अच्छा हो सकता है:

def openFile(fileName): File | Exception
    if not(File.Exist(fileName)):
        raise FileNotExist(fileName)
    else:
        return File.Open()

#This cause a exception:

theFile = openFile('not exist')

# But this, not:

theFile | err = openFile('not exist')

1

मेरी दृष्टि में आपकी भाषा को त्रुटियों का पता लगाने और संभालने के लिए एक सामान्य तंत्र प्रदान करना चाहिए। प्रोग्रामिंग त्रुटियों का संकलन समय पर (या जितनी जल्दी हो सके) पता लगाया जाना चाहिए और आमतौर पर कार्यक्रम समाप्ति के लिए नेतृत्व करना चाहिए। त्रुटियां जो अप्रत्याशित या गलत डेटा या अप्रत्याशित बाहरी परिस्थितियों से उत्पन्न होती हैं, का पता लगाया जाना चाहिए और उचित कार्रवाई के लिए उपलब्ध कराया जाना चाहिए, लेकिन जब भी संभव हो कार्यक्रम को जारी रखने की अनुमति दें।

प्रशंसनीय कार्यों में शामिल हैं (ए) समाप्त (बी) एक कार्रवाई के लिए उपयोगकर्ता को संकेत देता है (सी) त्रुटि लॉग (डी) एक सही मूल्य स्थानापन्न करें (ई) कोड में परीक्षण किया जा करने के लिए एक संकेतक सेट (एफ) एक त्रुटि हैंडलिंग दिनचर्या आह्वान। आप इनमें से कौन सा उपलब्ध कराते हैं और किन माध्यमों से आपको चुनाव करना है।

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

[उदाहरण के लिए, एक एक्सेल स्प्रेडशीट पर विचार करें। एक्सेल आपकी स्प्रेडशीट को समाप्त नहीं करता है क्योंकि एक संख्या अतिप्रवाह या जो भी हो। सेल को एक अजीब मूल्य मिलता है और आपको पता चलता है कि क्यों और इसे ठीक करना है।]

तो अपने प्रश्न का उत्तर देने के लिए: आपको निश्चित रूप से समाप्त नहीं करना चाहिए। आप NaN को स्थानापन्न कर सकते हैं लेकिन आपको वह दृश्यमान नहीं बनाना चाहिए, बस यह सुनिश्चित करें कि गणना पूरी हो गई है और एक अजीब उच्च मूल्य उत्पन्न करता है। और एक त्रुटि ध्वज सेट करें ताकि जिन उपयोगकर्ताओं को इसकी आवश्यकता है वे यह निर्धारित कर सकें कि त्रुटि हुई।

प्रकटीकरण: मैंने केवल एक ऐसी भाषा कार्यान्वयन (पॉवरफ्लेक्स) बनाया और 1980 के दशक में वास्तव में इस समस्या (और कई अन्य) को संबोधित किया। पिछले 20 वर्षों में गैर-प्रोग्रामर के लिए भाषाओं पर बहुत कम या कोई प्रगति नहीं हुई है, और आप कोशिश करने के लिए आलोचना के आकर्षण को आकर्षित करेंगे, लेकिन मुझे उम्मीद है कि आप सफल होंगे।


1

जब मैं ड्यूमिनीटर 0 होता है तो मुझे टर्नरी ऑपरेटर पसंद होता है जहां आप एक वैकल्पिक मूल्य प्रदान करते हैं।

एक और विचार जो मैंने नहीं देखा वह एक सामान्य "अमान्य" मान का उत्पादन करना है। एक सामान्य "इस चर का कोई मूल्य नहीं है क्योंकि कार्यक्रम ने कुछ बुरा किया है", जो अपने साथ एक पूर्ण स्टैक ट्रेस करता है। फिर, यदि आप कभी भी उस मूल्य को कहीं भी उपयोग करते हैं, तो परिणाम फिर से अमान्य है, शीर्ष पर किए गए नए ऑपरेशन के साथ (अर्थात यदि अमान्य मूल्य कभी भी एक अभिव्यक्ति में प्रकट होता है, तो पूरी अभिव्यक्ति अमान्य हो जाती है और कोई फ़ंक्शन कॉल का प्रयास नहीं किया जाता है; एक अपवाद बूलियन ऑपरेटर होना - सही या अमान्य सच है और गलत है और अमान्य गलत है - इसके अलावा भी कुछ अपवाद हो सकते हैं)। एक बार उस मूल्य को अब कहीं भी संदर्भित नहीं किया जाता है, तो आप पूरी श्रृंखला का एक अच्छा लंबा विवरण लॉग करते हैं जहां चीजें गलत थीं और हमेशा की तरह व्यवसाय जारी रखती हैं। हो सकता है कि प्रोजेक्ट लीड या कुछ और करने के लिए ट्रेस ईमेल करें।

शायद मूल रूप से शायद मोनाड की तरह कुछ। यह किसी और चीज के साथ काम करेगा जो विफल भी हो सकता है, और आप लोगों को अपने स्वयं के इनवैलिड के निर्माण की अनुमति दे सकते हैं। और यह कार्यक्रम तब तक चलता रहेगा जब तक कि त्रुटि बहुत गहरी नहीं है, जो कि वास्तव में यहाँ चाहता है, मुझे लगता है।


1

शून्य से विभाजित होने के दो मूल कारण हैं।

  1. एक सटीक मॉडल (जैसे पूर्णांक) में, आपको शून्य DBZ द्वारा विभाजन मिलता है क्योंकि इनपुट गलत है। यह एक प्रकार का DBZ है, जिसके बारे में हममें से अधिकांश लोग सोचते हैं।
  2. गैर-सटीक मॉडल (जैसे फ्लोटिंग पीटी) में, आपको इनपुट मान्य होने के बावजूद गोलाई-त्रुटि के कारण DBZ प्राप्त हो सकता है। यह वही है जो हम आम तौर पर नहीं सोचते हैं।

1 के लिए। आपको उपयोगकर्ताओं से वापस संवाद करना होगा कि उन्होंने एक गलती की है क्योंकि वे एक जिम्मेदार हैं और वे एक हैं जो सबसे अच्छा जानते हैं कि स्थिति को कैसे ठीक किया जाए।

2 के लिए। यह उपयोगकर्ता की गलती नहीं है, आप एल्गोरिथ्म, हार्डवेयर कार्यान्वयन आदि के लिए उंगली कर सकते हैं, लेकिन यह उपयोगकर्ता की गलती नहीं है, इसलिए आपको प्रोग्राम को समाप्त नहीं करना चाहिए या यहां तक ​​कि अपवाद भी नहीं फेंकना चाहिए (यदि इस मामले में अनुमति नहीं है)। तो कुछ उचित तरीके से संचालन जारी रखने के लिए एक उचित समाधान है।

मैं उस व्यक्ति को केस 1 के लिए पूछे गए प्रश्न को देख सकता हूं। इसलिए आपको उपयोगकर्ता से वापस संवाद करने की आवश्यकता है। जो भी फ्लोटिंग पॉइंट मानक का उपयोग करते हैं, Inf, -Inf, Nan, IEEE इस स्थिति में फिट नहीं होते हैं। मौलिक रूप से गलत रणनीति।


0

इसे भाषा में अस्वीकार करें। यह कहना है, एक संख्या से विभाजन को तब तक अस्वीकार करें जब तक कि यह शून्य न हो, आमतौर पर पहले परीक्षण करके। अर्थात।

int div = random(0,100);
int b = 10000 / div; // Error E0000: div might be zero

ऐसा करने के लिए आपको एक पूर्णांक के विपरीत एक नया संख्यात्मक प्रकार, एक प्राकृतिक संख्या की आवश्यकता होती है। यह हो सकता है ... मुश्किल ... से निपटने के लिए।
सर्व करें

@ सर्वे: नहीं, आप नहीं करेंगे। आप क्यों? संभावित मूल्यों को निर्धारित करने के लिए आपको संकलक में तर्क की आवश्यकता है, लेकिन आप चाहते हैं कि वैसे भी (कारणों का अनुकूलन करने के लिए)।
MSalters

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

@ सरवी: आप गलत हैं: एक कंपाइलर इस प्रकार की आवश्यकता के बिना उस स्थिति को ट्रैक कर सकता है, और उदाहरण के लिए जीसीसी पहले से ही ऐसा करता है। उदाहरण के लिए, C प्रकार intशून्य मानों की अनुमति देता है, लेकिन GCC अभी भी यह निर्धारित कर सकता है कि कोड विशिष्ट इनट्स शून्य कहां नहीं हो सकते।
MSalters

2
लेकिन केवल कुछ मामलों में; यह ऐसा नहीं कर सकता, सभी मामलों में 100% सटीकता के साथ। आपके पास गलत सकारात्मक या गलत नकारात्मक होंगे। यह सच साबित होता है। उदाहरण के लिए, मैं कोड का एक स्निपेट बना सकता था जो पूरा भी हो सकता है या नहीं भी । यदि कंपाइलर यह भी नहीं जान सकता है कि यह समाप्त हो गया है, तो यह कैसे जान सकता है कि परिणामी इंट गैर-शून्य है? यह सरल स्पष्ट मामलों को पकड़ सकता है, लेकिन सभी मामलों को नहीं ।
सर्विस

0

जैसा कि आप एक प्रोग्रामिंग भाषा लिखते हैं, आपको इस तथ्य का लाभ उठाना चाहिए और शून्य राज्य द्वारा वसीयत के लिए एक कार्रवाई को शामिल करना अनिवार्य करना चाहिए। <a = n / c: 0 div-by-zero-action

मुझे पता है कि मैंने जो अभी सुझाव दिया है वह अनिवार्य रूप से आपके पीएल में एक 'गोटो' जोड़ रहा है।

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