2010-05-21 48 views
47

मैं हमेशा सोच रहा था कि मैं एक फ़ंक्शन कैसे बना सकता हूं जो शक्ति की गणना करता है (उदा। 2) स्वयं। अधिकांश भाषाओं में इन्हें मानक पुस्तकालय में शामिल किया जाता है, अधिकांशतः pow(double x, double y), लेकिन मैं इसे स्वयं कैसे लिख सकता हूं?मैं खुद को एक पावर फ़ंक्शन कैसे लिख सकता हूं?

मैं for loops के बारे में सोच रहा था, लेकिन यह लगता है कि मेरी मस्तिष्क एक पाश में मिला (जब मैं एक गैर पूर्णांक प्रतिपादक के साथ एक बिजली करना चाहता था, 5 4.5 या नकारात्मक 2 -21) की तरह है और मैं चला गया पागल;)

तो, मैं एक कार्य कैसे लिख सकता हूं जो वास्तविक संख्या की शक्ति की गणना करता है? धन्यवाद


ओह, शायद याद रखना आवश्यक है: मैं जो शक्तियों (जैसे exp) है, जो यह अंततः बेकार होगा का उपयोग कार्यों का उपयोग नहीं कर सकते।

+3

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

+0

यह जांचें http://www.queryhome.com/27195/how-to-write-your-own-pow-function-in-c – user2794034

+0

संभावित डुप्लिकेट [मनमानी शक्ति/रूट की गणना कैसे करें?] (Http: //stackoverflow.com/questions/1375953/how-to-calculate-an-arbitrary-power-root) – jww

उत्तर

46

नकारात्मक शक्तियां कोई समस्या नहीं हैं, वे सकारात्मक शक्ति के विपरीत (1/x) हैं।

फ़्लोटिंग पॉइंट शक्तियां थोड़ी अधिक जटिल हैं; जैसा कि आप जानते हैं कि एक आंशिक शक्ति रूट के बराबर है (उदा। x^(1/2) == sqrt(x)) और आप यह भी जानते हैं कि समान आधार के साथ गुणा करने वाली शक्तियां उनके घाटे को जोड़ने के बराबर होती हैं।

सब से ऊपर के साथ

, आप:

  • Decompose the exponent in a integer part and a rational part
  • लूप के साथ पूर्णांक शक्ति की गणना करें (आप इसे कारकों में विघटित करने और आंशिक गणना का पुन: उपयोग करने के अनुकूल कर सकते हैं)।
  • अपनी पसंद के किसी भी एल्गोरिदम के साथ रूट की गणना करें (कोई भी पुनरावृत्ति अनुमान जैसे कि बिसेक्शन या न्यूटन विधि काम कर सकता है)।
  • परिणाम गुणा करें।
  • यदि एक्सपोनेंट नकारात्मक था, तो उलटा लागू करें।

उदाहरण:

2^(-3.5) = (2^3 * 2^(1/2)))^-1 = 1/(2*2*2 * sqrt(2)) 
+0

अच्छा दृष्टिकोण, लेकिन जब आप उदाहरण के साथ काम कर रहे हैं तो पूर्णांक का उपयोग करना मुश्किल हो जाएगा पाउ (10, 300)। – flodin

1

यह एक दिलचस्प अभ्यास है। यहां कुछ सुझाव दिए गए हैं, जिन्हें आपको इस क्रम में आजमाया जाना चाहिए:

  1. लूप का उपयोग करें।
  2. उपयोग प्रत्यावर्तन (नहीं बेहतर है, लेकिन दिलचस्प कोई भी कम)
  3. बेहद विभाजन और जीत
  4. उपयोग लघुगणक
+0

क्या आप मौजूद कोई भी एल्गोरिदम जानते हैं? धन्यवाद –

22

एक बी का उपयोग कर तकनीक के आधार पर आपके प्रत्यावर्तन का अनुकूलन = लॉग - 1 (लॉग (ए) * बी)

संपादित करें: हाँ, यह परिभाषा वास्तव में कुछ उपयोगी प्रदान करती है। उदाहरण के लिए, एक x86 पर, यह लगभग सीधे FYL2X (वाई * लॉग इन करें (एक्स)) और F2XM1 (2 एक्स -1) के लिए अनुवाद:

fyl2x 
fld st(0) 
frndint 
fsubr st(1),st 
fxch st(1) 
fchs 
f2xmi 
fld1 
faddp st(1),st 
fscale 
fstp st(1) 

कोड से कुछ अधिक समय समाप्त होता है आप उम्मीद कर सकते हैं, मुख्य रूप से क्योंकि F2XM1 केवल श्रेणी -1.0..1.0 में संख्याओं के साथ काम करता है। fld st(0)/frndint/fsubr st(1),st टुकड़ा पूर्णांक भाग से घटाता है, इसलिए हमें केवल अंश के साथ छोड़ दिया जाता है। हम उस पर F2XM1 लागू करते हैं, 1 को वापस जोड़ें, फिर एक्सपोनिएशन के पूर्णांक भाग को संभालने के लिए FSCALE का उपयोग करें।

+3

एक समस्या: 'लॉग^-1 (x) = exp (x) = e^x' –

+5

बहुत मजेदार रिकर्सिव परिभाषा: लॉगरिदम का उलटा भी एक शक्ति है, मुझे लगता है कि कोनिंग इसे अधिक मौलिक संचालन के साथ गणना करना चाहता है (योग, आराम, गुणा, विभाजन, आदि) – fortran

4

Wolfram functions शक्तियों की गणना के लिए विभिन्न प्रकार के सूत्र प्रदान करता है। उनमें से कुछ लागू करने के लिए बहुत सरल होगा।

19

आमतौर पर गणित पुस्तकालयों में pow(double, double) समारोह के कार्यान्वयन पहचान के आधार पर किया जाता है:

pow(x,y) = pow(a, y * log_a(x)) 

इस पहचान का उपयोग करना, आप केवल पता है कि कैसे एक मनमाना प्रतिपादक के लिए एक एकल संख्या a बढ़ाने के लिए की जरूरत है, और कैसे लॉगरिदम आधार a लेने के लिए। आपने एक जटिल बहु-परिवर्तनीय फ़ंक्शन को एक चर के दो कार्यों में प्रभावी रूप से बदल दिया है, और एक गुणा, जो कार्यान्वित करने में बहुत आसान है। क्योंकि यह फ्लोटिंग प्वाइंट गणित में लागू करने के लिए कुछ अच्छा गुण है e क्योंकि e^x और log_e(1+x) कुछ बहुत अच्छा गणितीय गुण होते हैं, और 2 - a की सबसे अधिक चुना मूल्यों e या 2 हैं।

यह कर की पकड़ इस तरह से वह यह है कि आप x और y की फ्लोटिंग प्वाइंट प्रतिनिधित्व की तुलना में अधिक सटीकता के लिए log_a(x) अवधि (और y के साथ अपने उत्पाद) की गणना करने की जरूरत है (आप पूर्ण सटीकता प्राप्त करना चाहते हैं)। उदाहरण के लिए, यदि x और y युगल हैं, और आप उच्च सटीकता परिणाम प्राप्त करना चाहते हैं, तो आपको उच्च-परिशुद्धता प्रारूप में मध्यवर्ती परिणामों (और अंकगणित) को स्टोर करने के लिए कुछ तरीके से आने की आवश्यकता होगी। इंटेल x87 प्रारूप 64-बिट पूर्णांक के रूप में एक सामान्य विकल्प है (हालांकि यदि आप वास्तव में एक शीर्ष-गुणवत्ता कार्यान्वयन चाहते हैं, तो आपको कुछ 96-बिट पूर्णांक कंप्यूटेशंस करने की आवश्यकता होगी, जो कुछ में थोड़ा दर्दनाक हैं भाषाओं)। यदि आप powf(float,float) लागू करते हैं, तो इससे निपटने में बहुत आसान है, क्योंकि आप इंटरमीडिएट कंप्यूटेशंस के लिए केवल double का उपयोग कर सकते हैं। यदि आप इस दृष्टिकोण का उपयोग करना चाहते हैं तो मैं इसके साथ शुरू करने की सलाह दूंगा।


एल्गोरिथ्म है कि मैं रेखांकित गणना करने के लिए pow ही संभव तरीका नहीं है। यह केवल उच्च गति वाले परिणाम देने के लिए सबसे उपयुक्त है जो एक निश्चित को प्राथमिकता सटीकता सीमा को पूरा करता है। यह कुछ अन्य संदर्भों में कम उपयुक्त है, और निश्चित रूप से दोहराए गए वर्ग [रूट]-एल्गोरिदम की तुलना में लागू करना बहुत कठिन है जिसे कुछ अन्य ने सुझाव दिया है।

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

+6

+1 यहां एक उदाहरण है: http://www.netlib.org/fdlibm/e_pow.c – stephan

1

सकारात्मक पूर्णांक शक्तियों की कुशलतापूर्वक गणना करने के लिए एक बेहतर एल्गोरिदम अतिरिक्त शेष गुणों का ट्रैक रखते हुए बार-बार आधार को चौकोर करता है।यहाँ पायथन में एक नमूना समाधान है कि समझते हैं और अपनी पसंद की भाषा में अनुवाद करने के अपेक्षाकृत आसान होना चाहिए:

def power(base, exponent): 
    remaining_multiplicand = 1 
    result = base 

    while exponent > 1: 
    remainder = exponent % 2 
    if remainder > 0: 
     remaining_multiplicand = remaining_multiplicand * result 
    exponent = (exponent - remainder)/2 
    result = result * result 

    return result * remaining_multiplicand 

यह नकारात्मक घातांक संभाल करने के लिए, तुम सब करने की है सकारात्मक संस्करण की गणना और से 1 विभाजित है परिणाम, ताकि उपर्युक्त कोड में एक साधारण संशोधन होना चाहिए। आंशिक एक्स्पोनेंट्स काफी है, और अधिक मुश्किल हो जाता है, क्योंकि यह अनिवार्य रूप से आधार है, जहां n = 1/abs(exponent % 1) के n वें-रूट की गणना और पूर्णांक भाग शक्ति गणना के परिणाम से परिणाम गुणा का अर्थ है:

power(base, exponent - (exponent % 1)) 

आप एक वांछित को जड़ों की गणना कर सकते न्यूटन की विधि का उपयोग कर सटीकता का स्तर। wikipedia article on the algorithm देखें।

+0

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

7

परिभाषा के अनुसार:

एक^b = exp (ख ln (एक))

जहां exp(x) = 1 + x + x^2/2 + x^3/3! + x^4/4! + x^5/5! + ...

जहां n! = 1 * 2 * ... * n

अभ्यास में, आप एक सरणी 1/n! के पहले 10 मूल्यों का संग्रहीत कर सकती है, और उसके बाद लगभग

exp(x) = 1 + x + x^2/2 + x^3/3! + ... + x^10/10!

क्योंकि 10! एक बड़ी संख्या है, तो 1/10! बहुत छोटा है (2.7557319224⋅10^-7)।

+2

@ पंडतजूह: फ़ॉर्मेटिंग को थोड़ा अच्छा बनाने की कोशिश करने के लिए धन्यवाद। लेकिन आप गलती से (मुझे आशा है) सूत्रों को पूरी तरह से गलत प्राप्त करने में कामयाब रहे। जब कोई x^n/n लिखता है! एक हमेशा मतलब है (x^n)/(n!), x^(n/n!) नहीं। –

+0

मैकलोरीन (और टेलर) श्रृंखला, कैलकुलस पाठों में आप सबसे उपयोगी चीजों में से एक सीख सकते हैं :-) – fortran

9

इसके साथ निपटने के लिए दो अलग-अलग मामले हैं: इंटीजर एक्सपोनेंट्स और आंशिक एक्सपोनेंट्स।

पूर्णांक एक्सपोनेंट्स के लिए, आप स्क्वायरिंग द्वारा एक्सपोनेंटिएशन का उपयोग कर सकते हैं।

def pow(base, exponent): 
    if exponent == 0: 
     return 1 
    elif exponent < 0: 
     return 1/pow(base, -exponent) 
    elif exponent % 2 == 0: 
     half_pow = pow(base, exponent // 2) 
     return half_pow * half_pow 
    else: 
     return base * pow(base, exponent - 1) 

दूसरा "एलिफ" यह भद्दा पाव समारोह से अलग करता है। यह फ़ंक्शन को O (n) के बजाय ओ (लॉग एन) रिकर्सिव कॉल करने की अनुमति देता है।

आंशिक एक्सपोनेंट्स के लिए, आप पहचान को^बी = सी^(बी * log_C (ए)) का उपयोग कर सकते हैं। सी = 2 लेना सुविधाजनक है, इसलिए एक^बी = 2^(बी * लॉग 2 (ए))। इससे 2^x और log2 (x) के लिए फ़ंक्शन लिखने में समस्या कम हो जाती है।

सी = 2 लेने के लिए सुविधाजनक कारण यह है कि फ़्लोटिंग-पॉइंट नंबर बेस -2 फ़्लोटिंग पॉइंट में संग्रहीत हैं। लॉग 2 (ए * 2^बी) = लॉग 2 (ए) + बी। इससे आपके लॉग 2 फ़ंक्शन को लिखना आसान हो जाता है: आपको केवल अंतराल पर, प्रत्येक सकारात्मक संख्या के लिए सटीक होने की आवश्यकता नहीं है [1, 2)। इसी तरह, 2^x की गणना करने के लिए, आप 2^(x का पूर्णांक भाग) * 2^(x का आंशिक भाग) गुणा कर सकते हैं। दूसरे भाग के लिए, फ्लोटिंग पॉइंट नंबर में स्टोर करने के लिए पहला भाग छोटा है, आपको अंतराल पर 0^x फ़ंक्शन की आवश्यकता है [0, 1)।

कठिन भाग 2^x और log2 (x) का अच्छा अनुमान लगा रहा है। Taylor series का उपयोग करना एक आसान तरीका है।

0

मैं निश्चित बिंदु लंबी अंकगणित का उपयोग कर रहा हूं और मेरा पाउ लॉग 2/exp2 आधारित है।नंबर से मिलकर बनता है:

  • int sig = { -1; +1 } Signum
  • DWORD a[A+B] संख्या
  • A आंशिक हिस्सा

के लिए DWORD रों की संख्या है संख्या

  • B का पूर्णांक भाग के लिए DWORD रों की संख्या है मेरी सरलीकृत समाधान यह है:

    //--------------------------------------------------------------------------- 
    longnum exp2 (const longnum &x) 
    { 
        int i,j; 
        longnum c,d; 
        c.one(); 
        if (x.iszero()) return c; 
        i=x.bits()-1; 
        for(d=2,j=_longnum_bits_b;j<=i;j++,d*=d) 
        if (x.bitget(j)) 
        c*=d; 
        for(i=0,j=_longnum_bits_b-1;i<_longnum_bits_b;j--,i++) 
        if (x.bitget(j)) 
        c*=_longnum_log2[i]; 
        if (x.sig<0) {d.one(); c=d/c;} 
        return c; 
    } 
    //--------------------------------------------------------------------------- 
    longnum log2 (const longnum &x) 
    { 
        int i,j; 
        longnum c,d,dd,e,xx; 
        c.zero(); d.one(); e.zero(); xx=x; 
        if (xx.iszero()) return c; //**** error: log2(0) = infinity 
        if (xx.sig<0) return c; //**** error: log2(negative x) ... no result possible 
        if (d.geq(x,d)==0) {xx=d/xx; xx.sig=-1;} 
        i=xx.bits()-1; 
        e.bitset(i); i-=_longnum_bits_b; 
        for (;i>0;i--,e>>=1) // integer part 
        { 
         dd=d*e; 
         j=dd.geq(dd,xx); 
         if (j==1) continue; // dd> xx 
         c+=i; d=dd; 
         if (j==2) break; // dd==xx 
        } 
        for (i=0;i<_longnum_bits_b;i++) // fractional part 
        { 
         dd=d*_longnum_log2[i]; 
         j=dd.geq(dd,xx); 
         if (j==1) continue; // dd> xx 
         c.bitset(_longnum_bits_b-i-1); d=dd; 
         if (j==2) break; // dd==xx 
        } 
        c.sig=xx.sig; 
        c.iszero(); 
        return c; 
    } 
    //--------------------------------------------------------------------------- 
    longnum pow (const longnum &x,const longnum &y) 
    { 
        //x^y = exp2(y*log2(x)) 
        int ssig=+1; longnum c; c=x; 
        if (y.iszero()) {c.one(); return c;} // ?^0=1 
        if (c.iszero()) return c; // 0^?=0 
        if (c.sig<0) 
        { 
         c.overflow(); c.sig=+1; 
         if (y.isreal()) {c.zero(); return c;} //**** error: negative x^noninteger y 
         if (y.bitget(_longnum_bits_b)) ssig=-1; 
        } 
        c=exp2(log2(c)*y); c.sig=ssig; c.iszero(); 
        return c; 
    } 
    //--------------------------------------------------------------------------- 
    

    जहां:

    _longnum_bits_a = A*32 
    _longnum_bits_b = B*32 
    _longnum_log2[i] = 2^(1/(2^i)) ... precomputed sqrt table 
    _longnum_log2[0]=sqrt(2) 
    _longnum_log2[1]=sqrt[tab[0]) 
    _longnum_log2[i]=sqrt(tab[i-1]) 
    longnum::zero() sets *this=0 
    longnum::one() sets *this=+1 
    bool longnum::iszero() returns (*this==0) 
    bool longnum::isnonzero() returns (*this!=0) 
    bool longnum::isreal() returns (true if fractional part !=0) 
    bool longnum::isinteger() returns (true if fractional part ==0) 
    int longnum::bits() return num of used bits in number counted from LSB 
    longnum::bitget()/bitset()/bitres()/bitxor() are bit access 
    longnum.overflow() rounds number if there was a overflow X.FFFFFFFFFF...FFFFFFFFF??h -> (X+1).0000000000000...000000000h 
    int longnum::geq(x,y) is comparition |x|,|y| returns 0,1,2 for (<,>,==) 
    

    सभी जब आप गणना करने के लिए 2^संख्या तो यह इस रूप में लिखा जा सकता है की जरूरत है आप, समझने के लिए इस कोड है कि बाइनरी प्रारूप में नंबर 2 की घात की राशि के होते हैं है की जरूरत है

    • 2^(b(-n)*2^(-n) + ... + b(+m)*2^(+m))

    जहां n आंशिक बिट और m हैं पूर्णांक बिट्स हैं। द्विआधारी रूप में 2 द्वारा गुणा/विभाजन सरल बिट स्थानांतरण है इसलिए यदि आप इसे एक साथ रखते हैं तो आपको exp2 के लिए कोड मिलता है। log2 बिनारू खोज पर आधारित है ... एमएसबी से एलएसबी तक परिणाम बिट्स को बदलकर जब तक यह खोज मूल्य से मेल नहीं खाता (तेज़ वर्ग गणना के लिए बहुत समान एल्गोरिदम)। उम्मीद है कि इस मदद करता है चीजों को स्पष्ट ...

  • +0

    पीएस मैं गणना/सादगी की सादगी के कारण लॉग/एक्स के लिए आधार 2 का उपयोग कर रहा हूं (आधार 10 और ई बाइनरी संख्याओं के साथ तेज़ गणना के लिए उपयुक्त नहीं हैं, अगर आईईवी बेस 10 की तुलना में बीसीडी कोडित संख्याओं का उपयोग किया जाता है तो आधार का उपयोग किया जाएगा) – Spektre

    2

    तीन आत्म कार्यान्वित कार्यों iPow(x, n), Ln(x) और Exp(x) का उपयोग करना, मैं गणना करने के लिए fPow(x, a), एक्स और एक जा रहा है युगल में सक्षम हूँ। नीचे दिए गए कार्यों में से कोई भी लाइब्रेरी फ़ंक्शंस का उपयोग नहीं करता है, लेकिन केवल पुनरावृत्ति। कार्यान्वित कार्यों के बारे में

    कुछ स्पष्टीकरण:

    (1) iPow(x, n): एक्स double है, एन int है। यह एक साधारण पुनरावृत्ति है, क्योंकि एन एक पूर्णांक है।

    (2) Ln(x): यह फ़ंक्शन टेलर श्रृंखला पुनरावृत्ति का उपयोग करता है। पुनरावृत्ति में उपयोग की जाने वाली श्रृंखला Σ (from int i = 0 to n) {(1/(2 * i + 1)) * ((x - 1)/(x + 1))^(2 * n + 1)} है। प्रतीक ^ पावर फ़ंक्शन Pow(x, n) को पहला फ़ंक्शन में कार्यान्वित करता है, जो सरल पुनरावृत्ति का उपयोग करता है।

    (3) Exp(x): यह फ़ंक्शन, टेलर सीरीज़ पुनरावृत्ति का उपयोग करता है। पुनरावृत्ति में उपयोग की जाने वाली श्रृंखला Σ (from int i = 0 to n) {x^i/i!} है। यहां, ^ पावर फ़ंक्शन को इंगित करता है, लेकिन यह पहला Pow(x, n) फ़ंक्शन कॉल करके गणना की गई है; इसके बजाय इसे d *= x/i का उपयोग करके, तीसरे फ़ंक्शन के भीतर, तथ्यात्मक के साथ समवर्ती रूप से लागू किया गया है। मुझे लगता है कि मुझे इस चाल का उपयोग का उपयोग करना था, क्योंकि इस फ़ंक्शन में, पुनरावृत्ति अन्य कार्यों के सापेक्ष कुछ और कदम उठाती है और अधिकांश समय के फैक्टरियल (i!) ओवरफ़्लो होती है। यह सुनिश्चित करने के लिए कि पुनरावृत्ति खत्म नहीं हो पाती है, इस भाग में पावर फ़ंक्शन एक साथ फैक्टोरियल के साथ पुनरावृत्त होता है। इस तरह, मैंने ओवरफ्लो को पार कर लिया।

    (4) fPow(x, a): x और एक दोनों युगल हैं। यह फ़ंक्शन कुछ भी नहीं करता है बल्कि ऊपर लागू अन्य तीन कार्यों को कॉल करता है। इस फ़ंक्शन में मुख्य विचार कुछ कैलकुलेशन पर निर्भर करता है: fPow(x, a) = Exp(a * Ln(x))। और अब, मेरे पास सभी कार्यों iPow, Ln और Exp पहले से ही पुनरावृत्ति के साथ हैं।

    एनबी। मैंने पुनरावृत्ति को रोकने के लिए कौन सा कदम तय करने के लिए constant MAX_DELTA_DOUBLE का उपयोग किया था। मैंने इसे 1.0E-15 पर सेट कर दिया है, जो कि युगल के लिए उचित लगता है। इसलिए, अगर (delta < MAX_DELTA_DOUBLE) पर पुनरावृत्ति बंद हो जाती है, तो आपको long double का उपयोग कर सकते हैं और MAX_DELTA_DOUBLE के लिए निरंतर मान घटा सकते हैं, उदाहरण के लिए 1.0E-18 (1.0E-18 न्यूनतम होगा)।

    यहां कोड है, जो मेरे लिए काम करता है।

    #define MAX_DELTA_DOUBLE 1.0E-15 
    #define EULERS_NUMBER 2.718281828459045 
    
    double MathAbs_Double (double x) { 
        return ((x >= 0) ? x : -x); 
    } 
    
    int MathAbs_Int (int x) { 
        return ((x >= 0) ? x : -x); 
    } 
    
    double MathPow_Double_Int(double x, int n) { 
        double ret; 
        if ((x == 1.0) || (n == 1)) { 
         ret = x; 
        } else if (n < 0) { 
         ret = 1.0/MathPow_Double_Int(x, -n); 
        } else { 
         ret = 1.0; 
         while (n--) { 
          ret *= x; 
         } 
        } 
        return (ret); 
    } 
    
    double MathLn_Double(double x) { 
        double ret = 0.0, d; 
        if (x > 0) { 
         int n = 0; 
         do { 
          int a = 2 * n + 1; 
          d = (1.0/a) * MathPow_Double_Int((x - 1)/(x + 1), a); 
          ret += d; 
          n++; 
         } while (MathAbs_Double(d) > MAX_DELTA_DOUBLE); 
        } else { 
         printf("\nerror: x < 0 in ln(x)\n"); 
         exit(-1); 
        } 
        return (ret * 2); 
    } 
    
    double MathExp_Double(double x) { 
        double ret; 
        if (x == 1.0) { 
         ret = EULERS_NUMBER; 
        } else if (x < 0) { 
         ret = 1.0/MathExp_Double(-x); 
        } else { 
         int n = 2; 
         double d; 
         ret = 1.0 + x; 
         do { 
          d = x; 
          for (int i = 2; i <= n; i++) { 
           d *= x/i; 
          } 
          ret += d; 
          n++; 
         } while (d > MAX_DELTA_DOUBLE); 
        } 
        return (ret); 
    } 
    
    double MathPow_Double_Double(double x, double a) { 
        double ret; 
        if ((x == 1.0) || (a == 1.0)) { 
         ret = x; 
        } else if (a < 0) { 
         ret = 1.0/MathPow_Double_Double(x, -a); 
        } else { 
         ret = MathExp_Double(a * MathLn_Double(x)); 
        } 
        return (ret); 
    } 
    
    +0

    टेलर का उपयोग न करें एक अंतराल पर एक समारोह का अनुमान लगाने के लिए श्रृंखला: http://lolengine.net/blog/2011/12/21/better-function-approximations –

    +0

    मैंने लिंक में दस्तावेज़ पढ़ा है। हालांकि दस्तावेज़ में विचार कुछ वैज्ञानिक परिणामों पर निर्भर करता है, ऊपर दिए गए मेरे कोड में पुनरावृत्ति में अधिकतम 15 से 20 कदम होते हैं (जब तक 'डेल्टा <1.0 ई -15') नहीं होता है। मैंने पूरी तरह से परीक्षण नहीं किया है, लेकिन महत्वपूर्ण आंकड़ों की संख्या (दशमलव बिंदु के बाद) सी में 'डबल' प्रकारों के लिए संभाल सकता है, सबसे अधिक '15' है, मुझे थोड़ा आश्वस्त है कि उपर्युक्त कोड यह काम करता है माना जाता है। – ssd

    1

    आप पाया जा पॉव समारोह इस तरह:

    static double pows (double p_nombre, double p_puissance) 
    { 
        double nombre = p_nombre; 
        double i=0; 
        for(i=0; i < (p_puissance-1);i++){ 
          nombre = nombre * p_nombre; 
         } 
        return (nombre); 
    } 
    

    आप पाया जा मंजिल समारोह इस तरह:

    static double floors(double p_nomber) 
    { 
        double x = p_nomber; 
        long partent = (long) x; 
    
        if (x<0) 
        { 
         return (partent-1); 
        } 
        else 
        { 
         return (partent); 
        } 
    } 
    

    सादर

    0

    अन्य उत्तरों में बहुत से दृष्टिकोण दिए गए हैं। यहां कुछ ऐसा है जो मैंने सोचा कि अभिन्न शक्तियों के मामले में उपयोगी हो सकता है।

    की n एक्स के पूर्णांक शक्ति एक्स मामले में, स्पष्ट दृष्टिकोण एक्स 1 गुणा ले जाएगा। इसे अनुकूलित करने के लिए, हम गतिशील प्रोग्रामिंग का उपयोग कर सकते हैं और सभी एक्स गुणाओं से बचने के लिए पहले गुणात्मक परिणाम का पुन: उपयोग कर सकते हैं। उदाहरण के लिए, 5 में, हम कह सकते हैं, के बैच बनाते हैं, यानी 5 एक बार गणना करें, 125 प्राप्त करें और फिर उसी तर्क का उपयोग करके 125 को क्यूब करें, प्रक्रिया में केवल 4 गुणा करने के बजाय सीधा तरीके से 8 गुणा।

    सवाल यह है कि बैच बी का आदर्श आकार क्या है ताकि गुणा की संख्या न्यूनतम हो। तो चलिए इसके लिए समीकरण लिखते हैं। पी संख्या के बैच का एक उत्पाद p- ले जाएगा: यदि f (x, ख) समारोह n एक्स की गणना उपरोक्त विधि का प्रयोग करने में अपरिहार्य गुणा की संख्या का प्रतिनिधित्व है, तो

    > f(x,b) = (x/b - 1) + (b-1)

    स्पष्टीकरण है 1 गुणा यदि हम एक्स बैक्शंस को बी बैचों में विभाजित करते हैं, तो प्रत्येक बैच के अंदर आवश्यक एक्स (बी/-1) गुणांक होंगे, और सभी बी बैचों के लिए आवश्यक बी -1 गुणक होंगे।

    अब हम बी के संबंध में इस फ़ंक्शन के पहले व्युत्पन्न की गणना कर सकते हैं और कम से कम गुणाओं के लिए बी प्राप्त करने के लिए इसे 0 तक समझा सकते हैं।सभी सकारात्मक लिए

    enter image description here

    :

    f'(x,b) = -x/b<sup>2</sup> + 1 = 0

    enter image description here

    अब वापस समारोह च में ख की इस मूल्य डाल (एक्स, ख) गुणा के कम से कम संख्या प्राप्त करने के एक्स, यह मान सीधे तरीके से गुणाओं से कम है।

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

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