2009-04-06 5 views
23

मानते हैं कि आपके पास एक कार्य 'सामान्यीकृत' है जो इनपुट के रूप में संख्याओं (वेक्टर का प्रतिनिधित्व करने) की सूची लेता है और सामान्यीकृत वेक्टर देता है। परिणाम क्या होना चाहिए जब वेक्टर सभी शून्य या उसके घटकों का योग शून्य है?आप शून्य वेक्टर

उत्तर

28

गणितीय रूप से बोलते हुए, शून्य वेक्टर को सामान्यीकृत नहीं किया जा सकता है। इसकी लंबाई हमेशा 0 रहेगी।

दिए गए वेक्टर v = (v1, v2, ..., vn) के लिए हमारे पास है: ||v|| = sqrt(v1^2 + v2^2 + ... + vn^2)। आइए याद रखें कि एक सामान्यीकृत वेक्टर वह है जिसमें ||v||=1 है।

तो v = 0 के लिए हमारे पास है: ||0|| = sqrt(0^2 + 0^2 + ... + 0^2) = 0। आप इसे कभी सामान्य नहीं कर सकते हैं।

यह भी ध्यान रखना महत्वपूर्ण है कि स्थिरता सुनिश्चित करने के लिए, आपको NaN या किसी अन्य शून्य मान को वापस नहीं करना चाहिए। v=0 का सामान्यीकृत रूप वास्तव में v=0 है।

+1

मुझे लगता है कि एक छोटा, लेकिन महत्वपूर्ण, सुधार का उल्लेख करना होगा कि वास्तविक कारण को सामान्यीकृत नहीं किया जा सकता है क्योंकि अंत में, सदिश की शून्य-लंबाई से विभाजित करने का प्रयास आवश्यक होगा, वह हिस्सा है जो वास्तव में संभव नहीं है/परिभाषित है। फिर भी, +1 – ray

0

(0,0,0) सामान्यीकृत (0,0,0) सामान्यीकृत हो सकता है और एक चेतावनी (या अपवाद) हो सकता है।
गणितीय रूप से यह परिभाषित नहीं किया गया है मुझे लगता है।

0

ठीक है, आपको शून्य से विभाजित करना होगा, जो आप नहीं कर सकते हैं, इसलिए मुझे लगता है कि अधिकांश भाषाओं में कुछ प्रकार के NaN मान होंगे।

संदर्भ:

3

सुंदर ज्यादा 0/0 की तरह (आप भी वेक्टर के लिए एक मनमाना दिशा लेने के लिए है) । अपवाद फेंकना चाहिए या NaN वापस करना चाहिए।

1

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

घटकों के साथ एक वेक्टर के लिए जो शून्य के बराबर है - ठीक है यह आपके द्वारा उपयोग किए जाने वाले मानदंड की परिभाषा पर निर्भर करता है। सादे पुराने एल 2-मानदंड (उत्पत्ति और वेक्टर के बीच यूक्लिडियन दूरी) के साथ सामान्यीकृत वेक्टर की गणना के लिए मानक सूत्र ठीक काम करना चाहिए क्योंकि यह पहले व्यक्तिगत घटकों को चौकोर करता है।

9

यह युवाल के सुझावों से भी बदतर है।

गणितीय रूप से, एक वेक्टर एक्स दिया गया है, आप एक नया वेक्टर x/|| x ||

जहां || || मानक है, जिसे आप शायद

|| के साथ यूक्लिडियन मानदंड के रूप में सोच रहे हैं। || = sqrt (dot (v, v)) = sqrt (sum_i x_i ** 2)

ये फ़्लोटिंग पॉइंट नंबर हैं, इसलिए शून्य से विभाजित करने के लिए केवल सुरक्षा के लिए पर्याप्त नहीं है, यदि आपके पास फ़्लोटिंग पॉइंट समस्या भी है x_i सभी छोटे हैं (वे कम हो सकते हैं और आप परिमाण खो देते हैं)।

असल में यह सब क्या उबलता है कि अगर आपको वास्तव में छोटे वैक्टरों को सही तरीके से संभालने में सक्षम होना चाहिए, तो आपको कुछ और काम करना होगा।

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

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

नीचे पंक्ति: सभी मामलों में संख्यात्मक काम सही ढंग से करना पहले की तुलना में अधिक कठिन है।

उदाहरण के लिए

, इस (सामान्य) आपरेशन के ऊपर एक अनुभवहीन रास्ता

  • सभी घटकों (x_i की) बहुत छोटा
  • किसी एक घटक बहुत बड़ी में किया (के साथ मेरे सिर संभावित समस्याओं के ऊपर से अधिकतम प्रतिनिधित्व योग्य वर्ग वर्ग) अनंतता वापस आ जाएगा। यह sqrt द्वारा घटक के रूप में उपलब्ध मात्रा में कटौती करता है।
  • अगर एक छोटे घटक के लिए एक बड़ा घटक के अनुपात बहुत बड़ी है, तो आप को प्रभावी ढंग से छोटे घटकों दिशा खो सकते हैं यदि आप सावधान
  • आदि
3

जैसा कि पहले ही उल्लेख किया गया है कई बार नहीं कर रहे हैं , आप एक शून्य वेक्टर सामान्य नहीं कर सकते हैं। तो, आपके विकल्प हैं:

  1. वापसी शून्य वेक्टर
  2. वापसी NaN
  3. वापसी एक सा संकेत करता है, तो वेक्टर सफलतापूर्वक सामान्यीकृत था, परिणाम के अलावा अगर सफल
  4. एक अपवाद फेंक

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

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

विकल्प 2 में विकल्प 1 के लिए एक समान समस्या है, लेकिन क्योंकि नाइन आमतौर पर ज़ीरो से अधिक ध्यान देने योग्य होते हैं, तो यह अधिक आसानी से प्रकट होता है।

मुझे लगता है कि विकल्प 3 सबसे अच्छा समाधान है, हालांकि यह इंटरफ़ेस को और अधिक जटिल बनाता है। इसके बजाय

vec3 = myVec.normalize(); 

कहने का अब आप की तरह

vec3 result; 
bool success = myVec.normalize(&result); 
if(success) 
    // vector was normalized 
else 
    // vector was zero (or small) 
+0

यदि आप अपना विकल्प चुनते हैं (0 को वापस करें) तो आपके परिणामों की शुद्धता के प्रभाव क्या हैं? –

0

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

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

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

5

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

  1. आप शून्य वेक्टर मामले के बारे में कुछ भी विशेष नहीं करते हैं। यदि आपके वेक्टर प्रकार में फ्लोटिंग पॉइंट टाइप किए गए निर्देशांक हैं, तो आपको परिणाम में शून्य या अनंत समन्वय मिलेगा (शून्य से विभाजित होने के कारण)।
  2. आप degenerate_case_exception फेंक देते हैं।
  3. आप अपनी प्रक्रिया में एक बूलियन is_degenerate_case आउटपुट पैरामीटर पेश करते हैं।

व्यक्तिगत रूप से मैं अपने कोड में हर जगह 3 दृष्टिकोण का उपयोग करता हूं। इसके फायदों में से एक यह है कि यह प्रोग्रामर को अपमानजनक मामलों से निपटने के लिए भूलने नहीं देता है।

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

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

0

यह सब इस बात पर निर्भर करता है कि आप "सामान्यीकृत" को कैसे परिभाषित करते हैं। इस शब्द का एक संभावित विस्तार यह कहना है कि इस ऑपरेशन का परिणाम किसी यूनिट लम्बाई वेक्टर है (मैं अधिकतर (1, 0, 0) का उपयोग करता हूं)। यह उदाहरण के लिए उपयोगी है जब आपको किसी दिए गए बिंदु से किसी सर्कल सीमा पर दिशा वापस करने के लिए सामान्यीकरण की आवश्यकता होती है।