2010-12-30 8 views

उत्तर

24

हां। C99 §7.20.6.2/2 का कहना है:

div, ldiv, और lldiv, कार्यों की गणना numer/denom और numer % denom एक भी आपरेशन में।

+0

धन्यवाद, http://www.cppreference.com/wiki/numeric/c/div ने इसे मेरे लिए भी साफ़ कर दिया। भाग्य और शेष गायब था। – Sheraz

9

कि है चाहिए/ और % ऑपरेटर्स का उपयोग करता है, तो आप दोनों भागफल और एक ही समय में शेष गणना करने के लिए चाहते हैं की तुलना में तेजी होने के लिए।

+1

édéric: जब आप कहते हैं "* माना * तेजी से होना", यह निहितार्थ है कि कभी-कभी ऐसा नहीं होता है? –

+1

@ स्टुअर्ट, बिल्कुल, @ जोनाथन वुड का जवाब और मेरी अगली टिप्पणी देखें। असल में, यदि आप प्रदर्शन बढ़ाने के लिए कार्यों के 'ldiv' परिवार का उपयोग करने पर विचार कर रहे हैं, तो आप सोच रहे हैं कि आपका कंपाइलर फ़ंक्शन कॉल से कुछ * सस्ता * के साथ आपके' उद्धरण + शेष 'गणना को अनुकूलित करने के लिए पर्याप्त स्मार्ट नहीं है , या आप उम्मीद कर रहे हैं कि 'ldiv' और इसके जैसे संकलक इंट्रिनिक्स हैं और वास्तविक कार्य नहीं हैं। –

+6

@ स्टुअर्ट गोलोडेट: यह बताते हुए कि एक्स वाई से तेज़ होना चाहिए, यह अनिवार्य है कि वाई एक्स से धीमा * होना चाहिए, जो कि एक अच्छा व्यवसाय नहीं है। यह सुनिश्चित करने का एकमात्र तरीका है कि यह तेज़ है, 'ldiv' में कार्यान्वयन के अनुकूलन का उपयोग करने से, '/' और '%' दोनों की गणना करने वाले कोड को देखने पर ऑप्टिमाइज़र को प्रतिबंधित करना होगा। लेकिन एक कंपाइलर खुद को क्यों सीमित कर देना चाहिए? –

21

विचार यह है कि/और% से परिणाम प्रोसेसर पर एक एकल डीआईवी निर्देश से निर्धारित किया जा सकता है। इसलिए, ऐतिहासिक रूप से, div() का उपयोग दोनों को प्राप्त करने के लिए एक अनुकूलित तरीका प्रदान करने के लिए किया जाता है।

हालांकि, मुझे पता चला है कि नए कंपाइलर किसी भी विभाजन में एक/और% ऑपरेशन को अनुकूलित करने में सक्षम हैं। उदाहरण के लिए, मैंने माइक्रोसॉफ्ट विजुअल सी ++ पर यह अनुकूलन देखा है। इन मामलों में, div() वास्तव में एक लाभ प्रदान नहीं करता है और वास्तव में, यदि कॉल शामिल है तो भी धीमा हो सकता है।

+3

+1 एक स्पष्ट 'इसके साथ भी परेशान न करें, आपके कंपाइलर की तुलना में शायद इससे भी ज्यादा स्मार्ट'। अब मैं जाउंगा और अपने जवाब में इटालिक्स जोड़ूंगा;) –

+7

मुझे लगता है कि किसी भी कंपाइलर जो लगातार प्रोसेसर निर्देश में लगातार% और/ऑपरेशंस को अनुकूलित करने के लिए पर्याप्त स्मार्ट है, भी div() को कॉल इनलाइन करने के लिए पर्याप्त स्मार्ट है । :/ –

+1

जब तक आप कुछ संकलक विकल्प * नहीं * इनलाइन मानक लाइब्रेरी कॉल पर सेट करते हैं। मुझे ऐसा क्यों लगता है कि ऐसा विकल्प मौजूद है ... शायद उस दिन से जब मैं सी में प्रोग्राम करता था? –

2

संक्षिप्त उत्तर: वास्तव में आधुनिक वातावरण में नहीं।

लोगों ने समझाया है कि div का लाभ कमजोर या यहां तक ​​कि अस्तित्वहीन क्यों है। यह वास्तव में और भी बदतर है: div और दोस्त टाइप युग्मन शुरू करते हैं जो अच्छी प्रथा को नुकसान पहुंचाता है (नीचे दोष खंड देखें)।

लाभ: शायद कोई भी

के रूप में अन्य उत्तर में कहा, div बजाय / और % संभवत सुनिश्चित करता है कि आपरेशन केवल विधानसभा स्तर पर एक बार किया जाता है बुला।

लेकिन सबसे आधुनिक संदर्भों में:

  1. सीपीयू इतनी अच्छी तरह से अनुकूलित किया है गणितीय क्रियाओं कि समय की एक गणना किया असंख्य के अंतरतम पाश में छोड़कर किसी भी प्रदर्शन आपरेशन दोहरा ने टक्कर मार दी शायद रास्ता से छोटा होता है अन्य प्रदर्शन हिट (जैसे अन्य कोड, कैश मिस आदि)। =>div का लाभ, यदि कोई है, आमतौर पर नगण्य है।
  2. / और % का उपयोग करते समय भी आधुनिक कंपाइलर्स वैसे ही एक विभाजन निर्देश उत्पन्न करके मात्रात्मक और शेष शेष उत्पन्न करके सही काम करते हैं। =>div के लिए कोई वास्तविक लाभ नहीं।

वापसी: div और दोस्तों, एक विशिष्ट प्रकार

संख्या का सही प्रकार (जैसे int या long) स्थिर में जाना जाता है, तो (जो है करने के लिए अपने कोड टाई अपने कोड को स्पष्ट रूप से पूर्णांक या लंबे समय हमेशा का उपयोग करता है), divint और ldiv के लिए लंबे समय तक ठीक है।

लेकिन अगर आप छोटे भागों अनावश्यक मान्यताओं से बचने में प्रोग्रामिंग के अच्छा अभ्यास का पालन करें, आप जल्दी से पता है कि div और ldiv संबंधों प्रकार int या long क्रमशः कोड का उपयोग कर। इसके विपरीत, / और % स्वचालित रूप से कोड क्लीनर रखने के मामले में वास्तव में किसी भी प्रकार का उपयोग करने के लिए समायोजित हो जाएगा।

यह दो मामलों में विशेष रूप से दिखाई दे रहा है:

  • आप सार दूर वास्तविक प्रकार के typedef का उपयोग करें - div भी सी में अनाड़ी है!
  • आप वास्तविक प्रकारों को दूर करने के लिए टेम्पलेट का उपयोग करते हैं - div टेम्पलेट्स को हरा देता है।

उदाहरण

नमूना नीचे div और दोस्तों हो जाता है का उपयोग कर कि कोड का उपयोग कर '/' और '%' स्पष्ट, आसान, और बंधा नहीं int करने के लिए, उन्हें लम्बे लंबा है या जो कुछ भी, कोड जबकि चलता अनाड़ी।

Testing with int 
my_math_func_div_WRONG says 6 
my_math_func_OVERKILL says 6 // Works but overkill cast to long 
my_math_func_GOOD says 6  // No div no headache. 

Testing with int in long type 
my_math_func_div_WRONG says 6 
my_math_func_OVERKILL says 6 // Works but overkill cast to long 
my_math_func_GOOD says 6  // No div no headache. 

Testing with actual long 
my_math_func_div_WRONG says 70503280 // FAIL 
my_math_func_OVERKILL says 500000006 
my_math_func_GOOD says 500000006  // No div no headache. 

स्रोत कोड:

#include <iostream> 

// '/' and '%' are smart about type. 
// This code is simple and will work with int, long, longlong, char, whatever. 
template<typename T> 
T my_math_func_GOOD(T number) 
{ 
    T quotient = number/10; 
    T remainder = number % 10; 
    // do something 
    return quotient + remainder; 
} 

// div and friends are not smart about type. 
// How do you write code smart about type with them ? 

// Plus adds dependency on C's stdlib. 
#include <stdlib.h> 
template<typename T> 
T my_math_func_div_WRONG(T number) 
{ 
    // This will always downcast to int. Defeats purpose of template. 
    div_t result = div(number, 10); 
    T quotient = result.quot; 
    T remainder = result.rem; 
    // do something 
    return quotient + remainder; 
} 

template<typename T> 
T my_math_func_OVERKILL(T number) 
{ 
    // This will always cast to long (up from int, OVERKILL, possibly down from long long, FAIL). Defeats purpose of template. 
    ldiv_t result = ldiv(number, 10); 
    T quotient = result.quot; 
    T remainder = result.rem; 
    // do something 
    return quotient + remainder; 
} 

template<typename T> 
void my_math_func_test(T number) 
{ 
    T n; 
    n = my_math_func_div_WRONG(number); 
    std::cout << "my_math_func_div_WRONG\tsays " << n << std::endl; // writes 6 
    n = my_math_func_OVERKILL(number); 
    std::cout << "my_math_func_OVERKILL\tsays " << n << std::endl; // writes 6 
    n = my_math_func_GOOD(number); 
    std::cout << "my_math_func_GOOD\tsays " << n << std::endl; // writes 6 
} 

// C99 allows absence of int argc, char **argv 
int main() 
{ 
    std::cout << std::endl << "Testing with int" << std::endl; 
    my_math_func_test<int>(42); 
    std::cout << std::endl << "Testing with int in long type" << std::endl; 
    my_math_func_test<long>(42); 
    std::cout << std::endl << "Testing with actual long" << std::endl; 
    my_math_func_test<long>(5000000042); 
    // std::cout << std::endl << "Testing with long long" << std::endl; 
    // my_math_func_test<long long>(50000000000000000042); 
} 
1

ठीक है, यह पुराना है, लेकिन मैं सिर्फ यहाँ ठोकर खाई। यहां सबसे महत्वपूर्ण अंतर यह है: div() का परिणाम परिभाषित किया गया है। सी मानक नहीं कहता है कि भाग्य को कैसे गोल करें। ऐसा इसलिए है क्योंकि संकलक मशीन के कार्यान्वयन का उपयोग करने में सक्षम होना चाहिए जो सीपीयू पर निर्भर करता है। दो अलग-अलग कार्यान्वयन मौजूद हैं: - -फिनिटी की ओर घूमते हुए -की ओर घूमते हुए।

div(), हालांकि बाद वाले को करने के लिए निर्दिष्ट किया गया है, और इसलिए पोर्टेबल है।

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