जब संभव हो तो विभाजन को गुणा से बदलना अच्छा होगा?


73

जब भी मुझे विभाजन की आवश्यकता होती है, उदाहरण के लिए, स्थिति की जाँच, मैं उदाहरण में विभाजन की अभिव्यक्ति को गुणा करना चाहूँगा:

मूल संस्करण:

if(newValue / oldValue >= SOME_CONSTANT)

नया संस्करण:

if(newValue >= oldValue * SOME_CONSTANT)

क्योंकि मुझे लगता है कि इससे बच सकते हैं:

  1. शून्य से विभाजन

  2. अतिप्रवाह जब oldValueबहुत छोटा होता है

क्या वह सही है? क्या इस आदत के लिए कोई समस्या है?


41
सावधान रहें कि नकारात्मक संख्याओं के साथ, दो संस्करण पूरी तरह से अलग चीजों की जांच करते हैं। क्या आप निश्चित हैं oldValue >= 0?
user2313067

37
भाषा पर निर्भर करता है (लेकिन सबसे विशेष रूप से सी के साथ), आप जो भी अनुकूलन के बारे में सोच सकते हैं, कंपाइलर आमतौर पर इसे बेहतर कर सकते हैं, -OR- , यह बिल्कुल समझ में नहीं आता है।
मार्क बेनिंगफील्ड

63
जब कोड X को X और Y शब्दार्थ रूप से समतुल्य नहीं किया जाता है तो कोड X को हमेशा बदलना एक "अच्छा अभ्यास" नहीं है। लेकिन यह हमेशा एक अच्छा विचार है कि एक्स और वाई को देखें, मस्तिष्क पर स्विच करें, इस बारे में सोचें कि आवश्यकताएं क्या हैं , और फिर निर्णय लें कि दोनों विकल्पों में से कौन सा विकल्प अधिक सही है। और इसके बाद, आपको यह भी सोचना चाहिए कि आपको यह सत्यापित करने के लिए कि कौन से परीक्षण आवश्यक हैं, आपको सिमेंटिक अंतर सही मिला।
डॉक्टर ब्राउन

12
@MarkBenningfield: जो कुछ भी नहीं, कंपाइलर दूर नहीं कर सकता विभाजित करके शून्य। "अनुकूलन" के बारे में आप सोच रहे हैं "गति अनुकूलन"। ओपी एक अन्य प्रकार के अनुकूलन के बारे में सोच रहा है - बग परिहार।
स्लीवेटमैन

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

जवाबों:


74

दो सामान्य मामलों पर विचार करने के लिए:

पूर्णांक अंकगणित

जाहिर है कि यदि आप पूर्णांक अंकगणित (जो काट-छाँट करते हैं) का उपयोग कर रहे हैं, तो आपको एक अलग परिणाम मिलेगा। यहाँ C # में एक छोटा सा उदाहरण दिया गया है:

public static void TestIntegerArithmetic()
{
    int newValue = 101;
    int oldValue = 10;
    int SOME_CONSTANT = 10;

    if(newValue / oldValue > SOME_CONSTANT)
    {
        Console.WriteLine("First comparison says it's bigger.");
    }
    else
    {
        Console.WriteLine("First comparison says it's not bigger.");
    }

    if(newValue > oldValue * SOME_CONSTANT)
    {
        Console.WriteLine("Second comparison says it's bigger.");
    }
    else
    {
        Console.WriteLine("Second comparison says it's not bigger.");
    }
}

आउटपुट:

First comparison says it's not bigger.
Second comparison says it's bigger.

फ्लोटिंग पॉइंट अंकगणित

इस तथ्य के अलावा कि विभाजन एक अलग परिणाम दे सकता है जब यह शून्य से विभाजित होता है (यह एक अपवाद उत्पन्न करता है, जबकि गुणा नहीं करता है), यह थोड़ा अलग गोलाई त्रुटियों और एक अलग परिणाम भी हो सकता है। C # में सरल उदाहरण:

public static void TestFloatingPoint()
{
    double newValue = 1;
    double oldValue = 3;
    double SOME_CONSTANT = 0.33333333333333335;

    if(newValue / oldValue >= SOME_CONSTANT)
    {
        Console.WriteLine("First comparison says it's bigger.");
    }
    else
    {
        Console.WriteLine("First comparison says it's not bigger.");
    }

    if(newValue >= oldValue * SOME_CONSTANT)
    {
        Console.WriteLine("Second comparison says it's bigger.");
    }
    else
    {
        Console.WriteLine("Second comparison says it's not bigger.");
    }
}

आउटपुट:

First comparison says it's not bigger.
Second comparison says it's bigger.

यदि आप मुझ पर विश्वास नहीं करते हैं, तो यहां एक फिडेल है जिसे आप निष्पादित कर सकते हैं और अपने लिए देख सकते हैं।

अन्य भाषाएँ भिन्न हो सकती हैं; ध्यान रखें, हालांकि, कई भाषाओं की तरह, C #, IEEE मानक (IEEE 754) फ्लोटिंग पॉइंट लाइब्रेरी को लागू करता है, इसलिए आपको अन्य मानकीकृत रन समयों में समान परिणाम प्राप्त करने चाहिए।

निष्कर्ष

यदि आप ग्रीनफ़ील्ड काम कर रहे हैं , तो आप शायद ठीक हैं।

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

यदि आप किसी सरणी या अन्य सामान्य कम्प्यूटेशनल कार्यों में तत्वों को गिनने जैसी चीजें कर रहे हैं, तो आप शायद ठीक हो जाएंगे। मुझे यकीन नहीं है कि गुणन विधि आपके कोड को कोई भी स्पष्ट कर देती है, हालांकि।

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


41
दूसरा वित्तीय सा। इस तरह का स्विच एकाउंटेंट से पिचकारो के साथ आपका पीछा करने के लिए कह रहा है। मुझे 5,000 लाइनें याद हैं, जहां मुझे "सही" उत्तर खोजने की तुलना में खाड़ी में पिचफ़ॉर्क रखने में अधिक प्रयास करना पड़ा था - जो वास्तव में आम तौर पर थोड़ा गलत था। .01% से दूर होने से कोई फर्क नहीं पड़ता था, बिल्कुल सुसंगत उत्तर अनिवार्य थे। इस प्रकार मुझे गणना को उस तरीके से करने के लिए मजबूर किया गया जो एक व्यवस्थित गोलमेज त्रुटि का कारण बना।
लोरेन Pechtel

8
5 सेंटी कैंडी खरीदने के बारे में सोचें (ऐसा कोई भी मौजूद नहीं है।) 20 टुकड़े खरीदें, "सही" उत्तर कोई कर नहीं था क्योंकि एक टुकड़े की 20 खरीद पर कोई कर नहीं था।
लोरेन Pechtel

24
@ लोरेनपेकटेल, ऐसा इसलिए है क्योंकि अधिकांश कर प्रणालियों में एक नियम (स्पष्ट कारणों के लिए) शामिल है कि कर प्रति लेन-देन पर लगाया जाता है, और कर वृद्धि के कारण होता है, जो कि दायरे के सबसे छोटे सिक्के से छोटा नहीं होता है, और करदाता के पक्ष में भिन्नात्मक मात्राएं नीचे होती हैं। वे नियम "सही" हैं क्योंकि वे वैध और सुसंगत हैं। पिचफोर्क वाले एकाउंटेंट शायद जानते हैं कि वास्तव में नियम एक तरह से क्या हैं जो कंप्यूटर प्रोग्रामर नहीं करेंगे (जब तक कि वे भी अनुभवी लेखाकार नहीं हैं)। 0.01% त्रुटि की संभावना एक संतुलन त्रुटि का कारण होगी, और एक संतुलन त्रुटि होना गैरकानूनी है।
स्टीव

9
क्योंकि मैंने ग्रीनफील्ड शब्द पहले कभी नहीं सुना है , मैंने इसे देखा। विकिपीडिया का कहना है कि "यह एक परियोजना है जिसमें पूर्व कार्य द्वारा लगाए गए बाधाओं का अभाव है"।
हेनरिक रिपा

9
@ सेव: मेरे बॉस ने हाल ही में "ग्रीनफ़ील्ड" को "ब्राउनफ़ील्ड" के विपरीत बताया। मैंने टिप्पणी की कि कुछ परियोजनाएँ "ब्लैकफ़ील्ड" की तरह हैं ...:
DevSolar

25

मुझे आपका प्रश्न पसंद है क्योंकि यह संभावित रूप से कई विचारों को शामिल करता है। कुल मिलाकर, मुझे संदेह है कि उत्तर यह है कि यह निर्भर करता है , संभवतः इसमें शामिल प्रकार और आपके विशिष्ट मामले में मूल्यों की संभावित सीमा।

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

आप सही हैं कि नया संस्करण शून्य से विभाजन से बचता है। निश्चित रूप से आपको एक गार्ड जोड़ने की आवश्यकता नहीं है (लाइनों के साथ if (oldValue != 0))। लेकिन क्या यह समझ में आता है? आपका पुराना संस्करण दो संख्याओं के बीच का अनुपात दर्शाता है। यदि भाजक शून्य है, तो आपका अनुपात अपरिभाषित है। यह आपकी स्थिति में अधिक सार्थक हो सकता है, अर्थात। आपको इस मामले में परिणाम नहीं देना चाहिए।

अतिप्रवाह के खिलाफ संरक्षण बहस का मुद्दा है। यदि आप जानते हैं कि newValueयह हमेशा से बड़ा है oldValue, तो शायद आप यह तर्क दे सकते हैं। हालांकि ऐसे मामले (oldValue * SOME_CONSTANT)भी हो सकते हैं जिनमें अतिप्रवाह भी होगा। इसलिए मुझे यहां ज्यादा फायदा नहीं दिख रहा है।

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

उपरोक्त सभी पर चिंतन करते हुए, सामान्य रूप से मुझे नहीं लगता कि पुराने संस्करण की तुलना में आपके नए संस्करण के साथ बहुत कुछ हासिल हुआ है, विशेष रूप से स्पष्टता में कमी को देखते हुए। हालांकि कुछ मामलों में विशिष्ट लाभ हो सकते हैं।


16
एहम, मनमाने ढंग से विभाजन की तुलना में अधिक कुशल होने के कारण मनमाने ढंग से वास्तविक दुनिया की मशीनों के लिए प्रोसेसर पर निर्भर नहीं है।
डिडुप्लिकेटर

1
पूर्णांक बनाम फ्लोटिंग पॉइंट अंकगणित का मुद्दा भी है। यदि अनुपात भिन्नात्मक है, तो विभाजन को फ़्लोटिंग पॉइंट में प्रदर्शन करने की आवश्यकता होती है, जिसमें कलाकारों की आवश्यकता होती है। कलाकारों को मिस करने से अनजाने में हुई गलती हो जाएगी। यदि अंश दो छोटे पूर्णांकों के बीच का अनुपात होता है, तो उन्हें पुन: व्यवस्थित करने से पूर्णांक अंकगणितीय में तुलना की जा सकती है। (किस बिंदु पर आपके तर्क लागू होंगे।)
rwong

@rwong हमेशा नहीं। कई भाषाओं में दशमलव भाग को हटाकर पूर्णांक विभाजन किया जाता है, इसलिए कोई भी कास्ट आवश्यक नहीं है।
टी। सार।

@ T.Sar आप जिस तकनीक का वर्णन करते हैं और उत्तर में वर्णित शब्दार्थ अलग हैं। शब्दार्थ यह है कि क्या प्रोग्रामर का उत्तर फ़्लोटिंग-पॉइंट या आंशिक मूल्य होना है; आपके द्वारा वर्णित तकनीक पारस्परिक गुणन द्वारा विभाजन है, जो कभी-कभी पूर्णांक विभाजन के लिए एक आदर्श सन्निकटन (प्रतिस्थापन) है। बाद की तकनीक आमतौर पर तब लागू होती है जब विभाजक को पहले से जाना जाता है, क्योंकि पूर्णांक-समय पर पूर्णांक पारस्परिक (2 ** 32 द्वारा स्थानांतरित) की व्युत्पत्ति की जा सकती है। ऐसा करने से रनटाइम फायदेमंद नहीं होगा क्योंकि यह अधिक सीपीयू-महंगा है।
रवांग

22

नहीं।

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

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

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

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

यह भी ध्यान दें: कंपाइलर अक्सर आपके लिए विभाजन का अनुकूलन करते हैं - जब ऐसा करना सुरक्षित हो।


11
-1 यह उत्तर वास्तव में सवाल पर फिट नहीं बैठता है, जो विभाजन के संभावित नुकसान के बारे में है - अनुकूलन के साथ कुछ भी नहीं करने के लिए
बेन कॉटरेल

13
@BenCottrell यह पूरी तरह से अच्छी तरह से फिट बैठता है। स्थिरता की कीमत पर व्यर्थ प्रदर्शन अनुकूलन में मूल्य कम होना है। सवाल से "क्या इस आदत के लिए कोई समस्या है?" - हाँ। यह जल्दी से पूरी तरह से अस्पष्ट लिखने की ओर ले जाएगा।
माइकल

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

5
@BenCottrell शायद आप इस ओर इशारा कर सकते हैं कि प्रश्न में शुद्धता के बारे में कोई भी उल्लेख है?
माइकल

5
@BenCottrell आपको बस 'मैं नहीं कर सकता' कहा होगा :)
माइकल

13

जो भी कम छोटी गाड़ी है उसका उपयोग करें और अधिक तार्किक समझ में आता है।

आमतौर पर , एक चर द्वारा विभाजन वैसे भी एक बुरा विचार है, आमतौर पर, भाजक शून्य हो सकता है।
एक स्थिरांक द्वारा विभाजन आमतौर पर सिर्फ इस बात पर निर्भर करता है कि तार्किक अर्थ क्या है।

यह दिखाने के लिए कुछ उदाहरण हैं कि यह स्थिति पर निर्भर करता है:

प्रभाग अच्छा:

if ((ptr2 - ptr1) >= n / 3)  // good: check if length of subarray is at least n/3
    ...

गुणन खराब:

if ((ptr2 - ptr1) * 3 >= n)  // bad: confusing!! what is the intention of this code?
    ...

गुणन भलाई:

if (j - i >= 2 * min_length)  // good: obviously checking for a minimum length
    ...

विभाजन खराब:

if ((j - i) / 2 >= min_length)  // bad: confusing!! what is the intention of this code?
    ...

गुणन भलाई:

if (new_length >= old_length * 1.5)  // good: is the new size at least 50% bigger?
    ...

विभाजन खराब:

if (new_length / old_length >= 2)  // bad: BUGGY!! will fail if old_length = 0!
    ...

2
मैं मानता हूं कि यह संदर्भ पर निर्भर करता है, लेकिन आपके पहले दो जोड़े उदाहरण बेहद खराब हैं। मैं दोनों में से किसी एक मामले में पसंद नहीं करूंगा।
माइकल

6
@ माइकल: उह ... आप (ptr2 - ptr1) * 3 >= nअभिव्यक्ति के रूप में समझने के लिए बस के रूप में आसान हो सकता है ptr2 - ptr1 >= n / 3? यह आपकी मस्तिष्क की यात्रा नहीं करता है और दो बिंदुओं के बीच के अंतर को तीन गुना करने के अर्थ को समझने की कोशिश कर रहा है? यदि यह आपके और आपकी टीम के लिए वास्तव में स्पष्ट है, तो आपके लिए अधिक शक्ति मुझे लगता है; मुझे सिर्फ धीमी गति से चलना चाहिए।
मेहरदाद

2
एक चर कहा जाता है nऔर एक मनमाना नंबर 3 दोनों मामलों में भ्रमित कर रहे हैं लेकिन, उचित नामों के साथ बदल दिया है, नहीं, मैं एक दूसरे की तुलना में अधिक भ्रामक नहीं मिल रहा है।
माइकल

1
ये उदाहरण वास्तव में गरीब नहीं हैं .. निश्चित रूप से 'बेहद गरीब' नहीं हैं - भले ही आप 'उचित नामों' में उप हों, वे तब भी कम मायने रखते हैं जब आप उन्हें खराब मामलों के लिए स्वैप करते हैं। अगर मैं किसी प्रोजेक्ट के लिए नया था तो मैं कुछ उत्पादन कोड को ठीक करने के लिए इस उत्तर में सूचीबद्ध 'अच्छे' मामलों को देखूंगा।
जॉन-एम

3

"जब भी संभव हो" कुछ भी करना बहुत अच्छा विचार है।

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

क्या सही है और सबसे पठनीय है। यदि आपके पास ठोस सबूत हैं कि सबसे पठनीय तरीके से कोड लिखने से प्रदर्शन समस्या होती है, तो आप इसे बदलने पर विचार कर सकते हैं। देखभाल, गणित और कोड समीक्षा आपके मित्र हैं।


1

कोड की पठनीयता के बारे में , मुझे लगता है कि गुणा कुछ मामलों में वास्तव में अधिक पठनीय है। उदाहरण के लिए, यदि कोई ऐसी चीज है जिसे आपको जांचना चाहिए कि क्या newValue5 प्रतिशत या उससे अधिक की वृद्धि हुई है oldValue, तो 1.05 * oldValueएक सीमा है जिसके खिलाफ परीक्षण करना है newValue, और यह लिखना स्वाभाविक है

    if (newValue >= 1.05 * oldValue)

लेकिन नकारात्मक संख्याओं से सावधान रहें जब आप चीजों को इस तरह से रिफलेक्टर करते हैं (या तो विभाजन को गुणन के साथ प्रतिस्थापित करते हैं, या विभाजन के साथ गुणन की जगह लेते हैं)। यदि आपके द्वारा माना गया दो शर्तें oldValueनकारात्मक हैं, तो नकारात्मक होने की गारंटी नहीं है; लेकिन लगता newValueहै कि वास्तव में -13.5 और oldValue-10.1 है। फिर

newValue/oldValue >= 1.05

सच का मूल्यांकन करता है , लेकिन

newValue >= 1.05 * oldValue

असत्य का मूल्यांकन करता है


1

बहुविकल्पी का उपयोग करके Invariant Integers द्वारा प्रसिद्ध पेपर डिवीजन पर ध्यान दें ।

संकलक वास्तव में गुणा कर रहा है, अगर पूर्णांक अपरिवर्तनीय है! विभाजन नहीं। 2 मानों की गैर-शक्ति के लिए भी ऐसा होता है। 2 डिवीजनों की शक्ति स्पष्ट रूप से बिट शिफ्ट का उपयोग करती है और इसलिए और भी तेज है।

हालांकि, गैर-अपरिवर्तनीय पूर्णांकों के लिए, कोड को अनुकूलित करना आपकी जिम्मेदारी है। यह सुनिश्चित करने से पहले सुनिश्चित करें कि आप वास्तव में एक वास्तविक अड़चन का अनुकूलन कर रहे हैं, और यह कि शुद्धता को पवित्र नहीं किया गया है। पूर्णांक अतिप्रवाह से सावधान रहें।

मुझे माइक्रो-ऑप्टिमाइज़ेशन की परवाह है, इसलिए मैं शायद ऑप्टिमाइज़ेशन संभावनाओं पर एक नज़र डालूँगा।

अपने कोड पर चलने वाले आर्किटेक्चर के बारे में भी सोचें। विशेष रूप से एआरएम का बेहद धीमा विभाजन है; आपको विभाजित करने के लिए एक फ़ंक्शन को कॉल करने की आवश्यकता है, एआरएम में कोई विभाजन निर्देश नहीं है।

साथ ही, 32-बिट आर्किटेक्चर पर, 64-बिट डिवीजन को ऑप्टिमाइज़ नहीं किया गया है, जैसा कि मुझे पता चला है


1

अपनी बात 2 पर उठाते हुए, यह वास्तव में बहुत छोटे के लिए अतिप्रवाह को रोक देगा oldValue। हालाँकि, अगर SOME_CONSTANTयह बहुत छोटा है तो आपका वैकल्पिक तरीका अंडरफ़्लो के साथ समाप्त हो जाएगा, जहाँ मूल्य का सही प्रतिनिधित्व नहीं किया जा सकता है।

और इसके विपरीत, क्या होता है यदि oldValueबहुत बड़ा है? आपके पास एक ही समस्या है, बस विपरीत तरीके से गोल।

यदि आप ओवरफ्लो / अंडरफ्लो के जोखिम से बचना चाहते हैं (या कम से कम), तो सबसे अच्छा तरीका यह जांचना है कि क्या newValueपरिमाण में निकटतम है oldValueया नहीं SOME_CONSTANT। आप तब उपयुक्त विभाजन ऑपरेशन चुन सकते हैं, या तो

    if(newValue / oldValue >= SOME_CONSTANT)

या

    if(newValue / SOME_CONSTANT >= oldValue)

और परिणाम सबसे सटीक होगा।

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

हालाँकि, यदि आपके आवेदन में आपके पास अतिप्रवाह / अंतर्प्रवाह का वास्तविक जोखिम है, तो संभवतः यह सही समाधान नहीं है। अधिक संभावना है, आपको आमतौर पर अपने एल्गोरिथ्म की संख्यात्मक स्थिरता की जांच करनी चाहिए, या शायद बस एक उच्च परिशुद्धता प्रतिनिधित्व के लिए जाना चाहिए।

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


0

सार्थक तरीकों और गुणों में सशर्त अंकगणित को प्रोत्साहित करें। न केवल अच्छा नामकरण आपको बताएगा कि "ए / बी" का क्या मतलब है , पैरामीटर की जांच और त्रुटि से निपटने से बड़े करीने से वहां भी छिप सकते हैं।

महत्वपूर्ण रूप से, इन विधियों को अधिक जटिल तर्क में रचा गया है, बाहरी जटिलता बहुत प्रबंधनीय है।

मैं कहूंगा कि गुणन प्रतिस्थापन एक उचित समाधान लगता है क्योंकि समस्या अ-परिभाषित है।


0

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

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