क्या डिस्टेंस के बजाय डिस्टेंस स्क्वेरड चेक्स का इस्तेमाल करने के कोई नुकसान हैं?


29

मैं मूल रूप से मेरी सभी दूरी (सदिश 3 लंबाई) की जाँच के लिए दूरी चुकता चेक का उपयोग करता हूं, क्योंकि एक वर्गमूल (सादे लंबाई की जाँच में) नहीं होने से प्रदर्शन में वृद्धि।

यह लग रहा है से, चुकता दूरी की जाँच हर स्थिति में ठीक काम:

if x^2 < y^2, then x < y, even when 0 < (x or y) < 1

मैं उन स्थितियों पर विचार नहीं कर रहा हूं जहां x या y 0 से कम है, क्योंकि दूरी और दूरी-वर्ग हमेशा सकारात्मक होने वाले हैं।

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

जवाबों:


41

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

बेशक वर्ग की लंबाई यूक्लिडियन दूरी की तुलना में काफी भिन्न है और इसलिए पथ प्रदर्शक जैसी चीजों के लिए एक बुरा उम्मीदवार है


16
वर्गमूल वास्तव में दूरी की जांच से सटीकता को हटा देता है। आप इसे 1 और 2 के बीच एक निश्चित बिंदु संख्या का वर्गमूल लेने के प्रयास के रूप में सोच सकते हैं और परिणाम (1 और sqrt (2) के बीच) को एक ही सीमा में संग्रहीत कर सकते हैं। कुछ दूरी जो x ^ 2 <y ^ 2 के रूप में तुलना करती हैं, वर्गमूल लेने के बाद x = y के रूप में तुलना करेंगी। चौकोर लंबाई की जाँच दोनों तेज और अधिक सटीक है।
जॉन कलसेबेक

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

1
सिवाय A * के मामले में। मुझे एक लेख पढ़ने की याद है, जिसने विभिन्न आंकड़ो के परीक्षण का वर्णन किया है और d^2भयानक प्रदर्शन किया है। ए * में |dx| + |dy|अच्छी तरह से काम करता है। मेरे पास लिंक नहीं है जैसा कि मैंने एक महीने या उससे पहले पढ़ा है।
जोनाथन डिकिंसन

3
A * के मामले में आप केवल दूरी की तुलना नहीं कर रहे हैं, बल्कि उन्हें जोड़ रहे हैं, इसलिए sqrt को छोड़ देने से फर्क पड़ता है।
amitp

1
@bobobobo मैं सहमत हूँ; मैंने ज्यादातर इसे दूसरी दिशा में एक संभावित तर्क को शूट करने के लिए बनाया, यानी सामान्य दूरी किसी तरह अधिक सटीक।
जॉन कैल्सबेक

14

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

x ^ 2 + y ^ 2! = (x + y) ^ 2


4

एकमात्र नुकसान मैं सोच सकता हूं कि बड़ी संख्या के साथ काम करते समय जो चुकता हो जाएगा।

उदाहरण के लिए, जावा में:

int x = Integer.MAX_VALUE / 1000000; //2147
int y = Integer.MAX_VALUE / 5000; //429496
System.out.println("x < y: " + (x < y)); //true
System.out.println("x*x: " + (x * x)); //4609609
System.out.println("y*y: " + (y * y)); //-216779712 - overflows!
System.out.println("x*x < y*y: " + (x * x < y * y)); //false - incorrect result due to overflow!

यह भी ध्यान देने योग्य है कि क्या होता है जब आप Math.pow () का उपयोग ठीक उसी संख्याओं के साथ करते हैं और डबल से इंट टू बैक कास्ट करते हैं Math.pow():

System.out.println("x^2: " + (int) (Math.pow(x, 2))); //4609609
System.out.println("y^2: " + (int) (Math.pow(y, 2))); //2147483647 - double to int conversion clamps to Integer.MAX_VALUE
System.out.println("x^2 < y^2: " + ((int) (Math.pow(x, 2)) < (int) (Math.pow(y, 2)))); //true - but for the wrong reason!

क्या यह काम कर रहा है? नहीं , इसने केवल सही उत्तर दिया है क्योंकि इससे y*yजुड़ा हुआ है Integer.MAX_VALUE, और x*xइससे कम है Integer.MAX_VALUE। अगर इस x*xपर भी नकेल कसी गई Integer.MAX_VALUEतो आपको गलत जवाब मिलेगा।

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


अधिकांश लोग floatनिर्देशांक के लिए एस का उपयोग करते हैं, जो कि लगभग 10^38नहीं के बाद ही ओवरफ्लो होता है int
बोबोबो

लेकिन 10 ^ 38 पर आपने इतनी सटीकता खो दी है कि आप वास्तव में सुनिश्चित नहीं हो सकते हैं कि आपकी दूरी की तुलना किसी भी अधिक मान्य है - अतिप्रवाह यहां एकमात्र समस्या नहीं है। देखें altdevblogaday.com/2012/02/05/dont-store-that-in-a-float ("टेबल्स" अनुभाग 1 बिलियन तक के सटीक नुकसान को संक्षेप में प्रस्तुत करता है)।
मैक्सिमस मिनिमस

आपको sqrt (x * x) के साथ एक ही अतिप्रवाह समस्या होगी। मैं आपकी बात नहीं देखता। यह मैनहट्टन की दूरी आदि के बारे में नहीं है
bogglez

@bogglez - यह निर्भर करता है कि आपका पुस्तकालय (या CPU) अप-कास्ट को दोगुना करता है या नहीं।
मैक्सिमस मिनिमस

3

एक बार जब मैं वर्ग दूरी में काम कर रहा था, और एक वर्ग किलोमीटर की दूरी के लिए चुकता दूरी जमा करने की गलती की ।

बेशक, आप ऐसा नहीं कर सकते, क्योंकि गणितीय रूप से,

(a^2+b^2+c^2+d^2)!=(a+b+c+d)^2

इसलिए, मैं वहाँ एक गलत परिणाम के साथ समाप्त हुआ। ऊप्स!


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

3

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


यह तर्कपूर्ण लगता है जो किसी दिए गए स्थिति के लिए बेहतर या बुरा होगा। मुझे याद है कि गणितज्ञ अक्सर बिंदुओं के सेट पर एक लाइन फिटिंग करते समय दूरी-वर्ग का उपयोग करना चुनते हैं। शायद वे ऐसा करते हैं क्योंकि यह अकेला आउटलेर के प्रभाव को कम करता है। आपके तीन-भवन के मामले में, आउटलेयर जोखिम नहीं हो सकता है। या शायद वे ऐसा करते हैं क्योंकि x^2काम करना आसान है |x|
joeytwiddle

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

सुधारों के लिए धन्यवाद। बेशक आप सही हैं, दूरी का वर्ग आउटलेर्स के लिए एक बड़ी त्रुटि उत्पन्न करता है , इसे कम करने के बजाय उनके प्रभाव को बढ़ाता है, जैसा कि मैंने ऊपर गलत कहा है। यह आकर्षक है कि गणना करने के लिए सबसे कम-निरपेक्ष-दूरी समाधान कितना कठिन है।
joeytwiddle

0

दूरी वर्ग का उपयोग करना लगभग हमेशा ठीक है और प्रदर्शन के लिए अच्छा है। निम्नलिखित विचार महत्वपूर्ण हैं:

यदि आप कई दूरियों के योग के बारे में सोचना चाहते हैं, तो दूरी चुकाना गलत होगा। उदाहरण के लिए, मेरी दो दूरियां हैं और मैं यह सुनिश्चित करना चाहता हूं कि उनका योग 10 से कम हो। निम्नलिखित कोड गलत है:

a = get_distance_squared(c,d);
b = get_distance_squared(e,f);
assert(a+b < 10^2);

यह निम्नलिखित अमान्य मामले में दावा करने में विफल रहता है: a=36और b=49। इस मामले में, पहली लंबाई 6 और दूसरी 7 है; उनकी राशि 10 से अधिक है, लेकिन वर्गों का योग 100 या अधिक नहीं है।

एक और विचार: वास्तविक-मूल्यवान दूरी के लिए, दूरी वर्ग हमेशा सकारात्मक होगा। यदि आप उदाहरण के लिए विस्थापन को माप रहे हैं, तो आपको नकारात्मक मूल्यों से निपटने की आवश्यकता हो सकती है, और उन्हें चुकता नहीं करना होगा।

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