2012-03-11 19 views
7

मैं How can I write a power function myself? के माध्यम से पढ़ रहा था और जवाब dan04 द्वारा दिए गए मेरा ध्यान पकड़ा जिसका मुख्य कारण मैं fortran द्वारा दिए गए जवाब के बारे में निश्चित नहीं हूँ, लेकिन मुझे लगता है कि ले लिया और यह लागू किया:स्वयं बनाया पॉव() C++

#include <iostream> 
using namespace std; 
float pow(float base, float ex){ 
    // power of 0 
    if (ex == 0){ 
     return 1; 
    // negative exponenet 
    }else if(ex < 0){ 
     return 1/pow(base, -ex); 
    // even exponenet 
    }else if ((int)ex % 2 == 0){ 
     float half_pow = pow(base, ex/2); 
     return half_pow * half_pow; 
    //integer exponenet 
    }else{ 
     return base * pow(base, ex - 1); 
    } 
} 
int main(){ 
    for (int ii = 0; ii< 10; ii++){\ 
     cout << "pow(" << ii << ".5) = " << pow(ii, .5) << endl; 
     cout << "pow(" << ii << ",2) = " << pow(ii, 2) << endl; 
     cout << "pow(" << ii << ",3) = " << pow(ii, 3) << endl; 
    } 
} 

हालांकि मुझे यकीन नहीं है कि मैंने इस अधिकार का अनुवाद किया है क्योंकि सभी कॉल 5 को एक्सपोनेंट रिटर्न के रूप में दे रहे हैं। उत्तर में यह बताता है कि इसे a^b = 2^(b * log2(a)) पर आधारित लॉग 2 (x) की आवश्यकता हो सकती है, लेकिन मुझे यह सुनिश्चित करने के बारे में अनिश्चितता है जैसा कि मुझे यकीन है कि इसे कहां रखा जाए, या यदि मैं इस अधिकार के बारे में भी सोच रहा हूं।

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

संपादित करें: क्या किसी को आंशिक एक्सपोनेंट के लिए फ़्लोटिंग-पॉइंट कार्यान्वयन पता है? (मैंने एक डबल कार्यान्वयन देखा है, लेकिन वह रजिस्टरों के साथ एक चाल का उपयोग कर रहा था, और मुझे फ्लोटिंग पॉइंट की आवश्यकता है, और सिर्फ एक चाल करने के लिए लाइब्रेरी जोड़ना मैं गणित पुस्तकालय समेत बेहतर होगा)

+3

या एक एफपीयू का जोड़ा खर्च? –

+2

आप आंशिक एक्सपोनेंट (कोड भी एक एक्सपोनेंट के लिए है) खो रहे हैं - मूल लिंक को देखते हुए, मुझे लगता है कि आप किसी ऐसे चीज की प्रतिलिपि बना रहे हैं जो केवल पूर्णांक एक्सपोनेंट का समर्थन करता है (इसलिए fractional के लिए परीक्षण विफल हो जाएंगे)। –

+0

@andrewcooke इसे डांग। क्या आप आवश्यक बदलावों को दिखाकर मेरी मदद कर सकते हैं – gardian06

उत्तर

14

नीचे पाउफ के वास्तविक कार्यान्वयन के लिंक हैं।

मुझे उम्मीद है कि सरल समाधानों में परिणाम में सटीकता की कमी होगी या इनफ और नाइन पैरामीटर को संभाल नहीं पाएगा।

http://opensource.apple.com/source/Libm/Libm-2026/Source/Intel/expf_logf_powf.c

http://opensource.apple.com/source/Libm/Libm-315/Source/ARM/powf.c

+0

+1 मैंने पाया कि यह था पावर लागू करने के लिए गैर-तुच्छ। एक समस्या, न्यू एन-एक्स की गणना करने के लिए न्यूटन-रैफसन उच्च एन और एक्स के लिए बहुत धीरे-धीरे (* नहीं * बहुत तेज़) अभिसरण करता है। कार्यान्वयन कि यह उत्तर लिंक करता है, स्पष्ट रूप से केवल 'फ्लोट' के लिए अलहॉट, इससे बचा जाता है। –

+0

यह एक मणि ive पिछले 3 हफ्तों के लिए खोज रहा है !! प्रविष्टि के लिए धन्यवाद! – nimig18

2

मुझे लगता है आप जिस एल्गोरिदम की तलाश में हैं वह 'nth root' हो सकता है। (K == 0 के लिए) 1 के एक प्रारंभिक अनुमान के साथ:

#include <iostream> 
using namespace std; 


float pow(float base, float ex); 

float nth_root(float A, int n) { 
    const int K = 6; 
    float x[K] = {1}; 
    for (int k = 0; k < K - 1; k++) 
     x[k + 1] = (1.0/n) * ((n - 1) * x[k] + A/pow(x[k], n - 1)); 
    return x[K-1]; 
} 

float pow(float base, float ex){ 
    if (base == 0) 
     return 0; 
    // power of 0 
    if (ex == 0){ 
     return 1; 
    // negative exponenet 
    }else if(ex < 0){ 
     return 1/pow(base, -ex); 
    // fractional exponent 
    }else if (ex > 0 && ex < 1){ 
     return nth_root(base, 1/ex); 
    }else if ((int)ex % 2 == 0){ 
     float half_pow = pow(base, ex/2); 
     return half_pow * half_pow; 
    //integer exponenet 
    }else{ 
     return base * pow(base, ex - 1); 
    } 
} 
int main_pow(int, char **){ 
    for (int ii = 0; ii< 10; ii++){\ 
     cout << "pow(" << ii << ", .5) = " << pow(ii, .5) << endl; 
     cout << "pow(" << ii << ", 2) = " << pow(ii, 2) << endl; 
     cout << "pow(" << ii << ", 3) = " << pow(ii, 3) << endl; 
    } 
    return 0; 
} 

परीक्षण:

pow(0, .5) = 0.03125 
pow(0, 2) = 0 
pow(0, 3) = 0 
pow(1, .5) = 1 
pow(1, 2) = 1 
pow(1, 3) = 1 
pow(2, .5) = 1.41421 
pow(2, 2) = 4 
pow(2, 3) = 8 
pow(3, .5) = 1.73205 
pow(3, 2) = 9 
pow(3, 3) = 27 
pow(4, .5) = 2 
pow(4, 2) = 16 
pow(4, 3) = 64 
pow(5, .5) = 2.23607 
pow(5, 2) = 25 
pow(5, 3) = 125 
pow(6, .5) = 2.44949 
pow(6, 2) = 36 
pow(6, 3) = 216 
pow(7, .5) = 2.64575 
pow(7, 2) = 49 
pow(7, 3) = 343 
pow(8, .5) = 2.82843 
pow(8, 2) = 64 
pow(8, 3) = 512 
pow(9, .5) = 3 
pow(9, 2) = 81 
pow(9, 3) = 729 
+0

खेद है कि अन्य परियोजनाओं पर काम करने के लिए। यह बताता है कि '.3' – gardian06

+0

कहने पर यह क्रैश होता है। मैंने 3 जोड़ने की कोशिश की, काम करने लगता है (मैं जीसीसी 4.5 का उपयोग कर रहा हूं)। लेकिन * बेस * == 0 ... – CapelliC

+0

के लिए संपादन देखें मैंने 1/3 एक्सपोनेंट जोड़ने की कोशिश की, मानों को खराब किया गया है, मैं और अधिक परीक्षण करने जा रहा हूं ... – CapelliC

6

मैं इस पत्र here जो वर्णन डबल परिशुद्धता के लिए घातीय समारोह अनुमान लगाने के लिए कैसे पर ध्यान दिया है। विकिपीडिया पर एक छोटे से शोध के बाद एक परिशुद्धता फ्लोटिंग पॉइंट प्रस्तुति के बारे में मैंने समकक्ष एल्गोरिदम तैयार किए हैं। वे केवल exp समारोह लागू किया, तो मैं लॉग के लिए एक व्युत्क्रम समारोह मिल गया और फिर बस किया था

POW(a, b) = EXP(LOG(a) * b). 

इस gcc4.6.2 संकलन एक पॉव समारोह लगभग 4 बार मानक पुस्तकालय के कार्यान्वयन की तुलना में तेजी पैदावार (O2 के साथ संकलन) ।

नोट: EXP के लिए कोड को मैंने पढ़ने वाले पेपर से लगभग क्रियापद प्रतिलिपि बनाई है और LOG फ़ंक्शन को here से कॉपी किया गया है।

यहाँ प्रासंगिक कोड है:

#define EXP_A 184 
    #define EXP_C 16249 

    float EXP(float y) 
    { 
     union 
     { 
     float d; 
     struct 
     { 
    #ifdef LITTLE_ENDIAN 
      short j, i; 
    #else 
      short i, j; 
    #endif 
     } n; 
     } eco; 
     eco.n.i = EXP_A*(y) + (EXP_C); 
     eco.n.j = 0; 
     return eco.d; 
    } 

    float LOG(float y) 
    { 
     int * nTemp = (int*)&y; 
     y = (*nTemp) >> 16; 
     return (y - EXP_C)/EXP_A; 
    } 

    float POW(float b, float p) 
    { 
     return EXP(LOG(b) * p); 
    } 

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

3

मुझे लगता है कि आप टेलर की श्रृंखला का उपयोग करके इसे हल करने का प्रयास कर सकते हैं, इसे जांचें। http://en.wikipedia.org/wiki/Taylor_series

टेलर की श्रृंखला के साथ आप पहले से ज्ञात परिणामों जैसे कि 3^4 का उपयोग करके गणना को हल करने के लिए किसी भी मुश्किल को हल कर सकते हैं। इस मामले में आपके पास 3^4 = 81 है

3^3.8 = 81 + 3.8 * 3 (3.8 - 4) + .. + .. और इस पर निर्भर करता है कि आपका एन कितना बड़ा होगा आपकी समस्या का करीब समाधान।

+0

विकसित करता हूं टेलर श्रृंखला वक्र फिटिंग के प्रश्न पर आती है, और सटीक मूल्य उत्पन्न करने के लिए उपयोग की जाने वाली शर्तों की उचित संख्या जानने की आवश्यकता होती है। कुछ के लिए और आप आसानी से निरंतर वृद्धि/कमी, और कई, और अपनी बर्बाद प्रक्रियाओं को आसानी से हिट कर सकते हैं। क्या संक्षेप में के संख्या पर एक उचित सुझाव है? – gardian06

+0

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

+0

टेलर श्रृंखला केवल एक बिंदु पर अनुमानित है जहां एक मिनीमैक्स एल्गोरिदम जैसे कि (चेबिशहेव, रीमेज़) एक बाध्य हैं, जो इष्टतम इक्की-रिपल त्रुटि देता है। – nimig18

1

मैं और मेरे दोस्त को एक ही समस्या का सामना करना पड़ा, जबकि हम ओपनजीएल प्रोजेक्ट पर हैं और गणित कुछ मामलों में पर्याप्त नहीं है।हमारे प्रशिक्षक को भी वही समस्या थी और उसने हमें पूर्णांक और फ़्लोटिंग भागों में बिजली को अलग करने के लिए कहा। उदाहरण के लिए, यदि आप x^11.5 की गणना करना चाहते हैं तो आप sqrt (x^115, 10) की गणना कर सकते हैं जिसके परिणामस्वरूप अधिक सटीक परिणाम हो सकते हैं।

+0

इसके साथ शुरू करने के लिए एक बड़ा एक्सपोनिएशन की आवश्यकता होगी। यद्यपि यह फ़्लोटिंग पॉइंट शक्तियों की गणना करने के लिए सरल हो सकता है, यह पावर फ़ंक्शन के भीतर किए गए रिकर्सिव या लूप कॉल की संख्या को भी बढ़ाएगा (इस पर विचार करते हुए कि जब तक बिट गणित नहीं किया जाता है, इसे किसी प्रकार की लूप की आवश्यकता होती है) – gardian06

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