2015-09-07 11 views
16

documentation of std::hypot का कहना है कि:`जब उपयोग करने के लिए std :: hypot (एक्स, वाई)` `से अधिक std :: sqrt (एक्स * x + y * वाई)`

का वर्गमूल गणना करता है गणना के मध्यवर्ती चरणों में अनुचित ओवरफ्लो या अंडरफ्लो के बिना एक्स और वाई के वर्गों का योग।

मैं एक परीक्षण का मामला जहां std::hypot तुच्छ sqrt(x*x + y*y) से अधिक इस्तेमाल किया जाना चाहिए गर्भ धारण करने के लिए संघर्ष।

निम्नलिखित परीक्षण से पता चलता है कि std::hypot बेकार गणना से लगभग 20x धीमी है।

#include <iostream> 
#include <chrono> 
#include <random> 
#include <algorithm> 

int main(int, char**) { 
    std::mt19937_64 mt; 
    const auto samples = 10000000; 
    std::vector<double> values(2 * samples); 
    std::uniform_real_distribution<double> urd(-100.0, 100.0); 
    std::generate_n(values.begin(), 2 * samples, [&]() {return urd(mt); }); 
    std::cout.precision(15); 

    { 
     double sum = 0; 
     auto s = std::chrono::steady_clock::now(); 
     for (auto i = 0; i < 2 * samples; i += 2) { 
      sum += std::hypot(values[i], values[i + 1]); 
     } 
     auto e = std::chrono::steady_clock::now(); 
     std::cout << std::fixed <<std::chrono::duration_cast<std::chrono::microseconds>(e - s).count() << "us --- s:" << sum << std::endl; 
    } 
    { 
     double sum = 0; 
     auto s = std::chrono::steady_clock::now(); 
     for (auto i = 0; i < 2 * samples; i += 2) { 
      sum += std::sqrt(values[i]* values[i] + values[i + 1]* values[i + 1]); 
     } 
     auto e = std::chrono::steady_clock::now(); 
     std::cout << std::fixed << std::chrono::duration_cast<std::chrono::microseconds>(e - s).count() << "us --- s:" << sum << std::endl; 
    } 
} 

तो मैं मार्गदर्शन के लिए पूछ रहा हूँ, जब मैं std::hypot(x,y) का उपयोग अधिक बहुत तेजी से std::sqrt(x*x + y*y) सही परिणाम प्राप्त करने के आवश्यक है।

स्पष्टीकरण: मैं उत्तर चुनें जो लागू x और y बिन्दु संख्या तैर रहे हैं जब की तलाश में हूँ। अर्थात। तुलना:

double h = std::hypot(static_cast<double>(x),static_cast<double>(y)); 

रहे हैं:

double xx = static_cast<double>(x); 
double yy = static_cast<double>(y); 
double h = std::sqrt(xx*xx + yy*yy); 
+1

मुझे लगता है कि आपको इसे 'std :: abs (std :: complex (x, y)) से तुलना करना चाहिए, जैसा कि [std :: hypot] (http://en.cppreference.com/w/ सीपीपी/न्यूमेरिक/गणित/हाइपोट) पृष्ठ –

+0

देर हो चुकी है, लेकिन cppreference दस्तावेज़ भी एक नोट के रूप में कहता है (इसलिए मानक द्वारा कोई गारंटी नहीं) कि "कार्यान्वयन आमतौर पर 1 उल से कम (अंतिम स्थान पर इकाइयों) की सटीकता की गारंटी देता है।" 'एक्स * एक्स + वाई * वाई 'परिशुद्धता के कुछ बिट खो सकता है, अगर निकटतम सेट के साथ दौर के साथ। इसका मतलब है कि 'std :: sqrt (x * x + y * y) 'थोड़ा या दो से बंद हो सकता है। उस गारंटी प्राप्त करने के लिए 'std :: sqrt (x * x + y * y) 'से बेहतर एल्गोरिदम आवश्यक है। (जारी) –

+0

मामलों को और भी खराब बनाने के लिए, मान लीजिए कि आपने गोल के साथ मिलकर काम किया है? वह निश्चित रूप से उस उप-उल परिशुद्धता को प्राप्त करने के तरीके में प्राप्त होगा। 'हाइपोट' को राउंडिंग सेट करना है ताकि सटीकता प्राप्त हो सके और फिर अपनी सेटिंग्स में राउंडिंग को पुनर्स्थापित कर सकें। राउंडिंग व्यवहार की यह सेटिंग और रीसेटिंग 'std: hypot (x, y) 'std :: sqrt (x * x + y * y)' से काफी धीमी है। –

उत्तर

19

जवाब प्रलेखन आप उद्धृत

x और y, के वर्गों का योग का वर्गमूल गणना करता अनुचित बिना में है गणना के मध्यवर्ती चरणों में अतिप्रवाह या अंडरफ्लो।

यदि x*x + y*y ओवरफ्लो, तो यदि आप मैन्युअल रूप से गणना करते हैं, तो आपको गलत जवाब मिल जाएगा। यदि आप std::hypot का उपयोग करते हैं, हालांकि, यह गारंटी देता है कि मध्यवर्ती गणना अधिक नहीं होगी।

आप इस असमानता here का एक उदाहरण देख सकते हैं।

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

+2

'std :: hypot' के पैरामीटर फ़्लोटिंग-पोंट प्रकार हैं, इसलिए यदि आप यहां int का उपयोग करते हैं तो इसे फ़्लोटिंग-पॉइंट पर भी बढ़ावा दिया जाएगा। –

+0

शायद मेरे प्रश्न में 100% स्पष्ट नहीं हो सकता है। मुझे केवल दो के बीच अंतर में दिलचस्पी है जब 'डबल' सटीक तर्क का उपयोग किया जाता है। क्योंकि पूर्णांक ओवरफ्लो को प्रकार के प्रचार द्वारा नियंत्रित किया जाता है, न कि 'हाइपोट' फ़ंक्शन। लेकिन 'हाइपोट' में कुछ इसे निष्पक्ष कार्यान्वयन (यहां तक ​​कि प्रकार के प्रचार के साथ) से 20x धीमा बनाता है। यह क्यों है और यह मेरी टुशी को कब बचाएगा? –

+0

जैसा देखा जा सकता है [उदाहरण में यहां] (http://coliru.stacked-crooked.com/a/d957adbf7ab753a0) डबल परिशुद्धता तर्कों का उपयोग करते समय कोई असमानता नहीं है। विशेष रूप से मैं 'डबल एक्स, वाई' की तलाश में हूं जहां एक असमानता दिखाई देगी। –

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