C कैसे पाप की गणना करता है () और अन्य गणित कार्य करता है?


248

मैं .NET disassemblies और GCC स्रोत कोड के माध्यम से काम कर रहा हूं, लेकिन वास्तविक कार्यान्वयन sin()और अन्य गणित कार्यों के लिए कहीं भी खोजने के लिए प्रतीत नहीं हो सकता ... वे हमेशा कुछ और संदर्भित करते हैं।

क्या कोई मुझे उन्हें खोजने में मदद कर सकता है? मुझे लगता है कि यह संभावना नहीं है कि सभी हार्डवेयर जो C हार्डवेयर में ट्रिगर कार्यों का समर्थन करेंगे, इसलिए कहीं न कहीं एक सॉफ्टवेयर एल्गोरिदम होना चाहिए , है ना?


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


2
कृपया ध्यान दें कि यह कार्यान्वयन निर्भर करता है। आपको यह निर्दिष्ट करना चाहिए कि आपको किस कार्यान्वयन में सबसे अधिक रुचि है।
जेसन

3
मैंने .NET और C को टैग किया क्योंकि मैंने दोनों जगहों पर देखा और यह भी पता नहीं लगा सका। यद्यपि .NET डिस्सैसफॉर्म को देखकर ऐसा लगता है कि यह अनवांटेड C में कॉल किया जा सकता है, जहाँ तक मुझे पता है कि उनका समान कार्यान्वयन है।
हांक

जवाबों:


213

GNU लिबम में, कार्यान्वयन sinप्रणाली-निर्भर है। इसलिए, आप प्रत्येक प्लेटफ़ॉर्म के लिए, कहीं न कहीं sysdeps के उपयुक्त उपनिर्देशन में कार्यान्वयन पा सकते हैं ।

एक निर्देशिका में सी में एक कार्यान्वयन शामिल है, आईबीएम द्वारा योगदान दिया गया है। अक्टूबर 2011 से, यह वह कोड है जो वास्तव में तब चलता है जब आप sin()एक विशिष्ट x86-64 लिनक्स सिस्टम पर कॉल करते हैं । यह स्पष्ट रूप से fsinविधानसभा निर्देश से तेज है । स्रोत कोड: sysdeps / ieee754 / dbl-64 / s_sin.c , देखें __sin (double x)

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

  • जब एक्स बहुत है बहुत 0 के करीब, sin(x) == xसही जवाब है।

  • थोड़ा और बाहर, sin(x)टेलर श्रृंखला का उपयोग करता है। हालांकि, यह केवल 0 के पास सटीक है, इसलिए ...

  • जब कोण लगभग 7 ° से अधिक होता है, तो एक अलग एल्गोरिथ्म का उपयोग किया जाता है, दोनों पाप (x) और कॉस (x) के लिए टेलर-श्रृंखला सन्निकटन की गणना करता है, फिर सन्निकटन को परिष्कृत करने के लिए पूर्व-निर्धारित तालिका से मानों का उपयोग करता है।

  • कब | x | > 2, उपरोक्त एल्गोरिदम में से कोई भी काम नहीं करेगा, इसलिए कोड 0 से करीब कुछ मानों की गणना करके शुरू होता है जिसे sinया cosइसके बदले खिलाया जा सकता है ।

  • X के साथ एक NaN या अनंत होने से निपटने के लिए अभी तक एक और शाखा है ।

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

double t = (x * hpinv + toint);
double xn = t - toint;

0 के करीब x को कम करने के लिए (कभी-कभी) उपयोग किया जाता है जो x से by / 2, विशेष रूप से xn× specifically / 2 के कई से भिन्न होता है । जिस तरह से यह विभाजन या शाखाओं के बिना किया जाता है, बल्कि चालाक है। लेकिन वहाँ कोई टिप्पणी नहीं है!


जीसीसी / ग्लिब के पुराने 32-बिट संस्करणों ने fsinनिर्देश का उपयोग किया , जो कुछ इनपुटों के लिए आश्चर्यजनक रूप से गलत है। कोड की सिर्फ 2 पंक्तियों के साथ इसे दर्शाते हुए एक आकर्षक ब्लॉग पोस्ट है

sinशुद्ध सी में fdlibm का कार्यान्वयन ग्लिबेक की तुलना में बहुत सरल है और अच्छी तरह से टिप्पणी की गई है। स्रोत कोड: fdlibm / s_sin.c और fdlibm / k_sin.c


35
यह देखने के लिए कि यह वास्तव में x86 पर चलने वाला कोड है: कॉल करने वाले प्रोग्राम को संकलित करें sin(); टाइप करें gdb a.out, फिर break sin, तब run, फिर disassemble
जेसन ओरेंडोर्फ

5
@ हेनरी: यह सोचने की गलती न करें कि हालांकि यह अच्छा कोड है। यह वास्तव में भयानक है , उस तरह से कोड करना न सीखें!
थॉमस बोनी

2
@ और हम्म, आप सही कह रहे हैं, आईबीएम कोड fdlibm की तुलना में बहुत भयानक लगता है। मैंने fdlibm की दिनचर्या के लिए लिंक जोड़ने के उत्तर को संपादित किया।
जेसन ओरेंडोर्फ

3
__kernel_sin@ हेनरी : को k_sin.c में परिभाषित किया गया है, हालांकि, और यह शुद्ध सी है। इसे फिर से क्लिक करें- मैंने पहली बार URL को बॉट किया।
जेसन ओरेंडोर्फ

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

66

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

चिप्स ट्रिगर कार्यों की गणना करने के लिए टेलर श्रृंखला का उपयोग नहीं करते हैं, कम से कम पूरी तरह से नहीं। सबसे पहले वे CORDIC का उपयोग करते हैं , लेकिन वे CORDIC का परिणाम चमकाने के लिए या बहुत छोटे कोणों के लिए उच्च सापेक्ष सटीकता के साथ साइनिंग जैसे विशेष मामलों के लिए एक छोटी टेलर श्रृंखला का उपयोग भी कर सकते हैं। अधिक स्पष्टीकरण के लिए, यह StackOverflow उत्तर देखें ।


10
ट्रान्सेंडैंटल मैथ फ़ंक्शंस जैसे साइन और कोसाइन को माइक्रोकोड में या वर्तमान 32-बिट डेस्कटॉप और सर्वर प्रोसेसर में हार्डवेयर निर्देशों के रूप में लागू किया जा सकता है। यह हमेशा ऐसा नहीं होता था, जब तक कि i486 (DX) तक सभी फ्लोटिंग पॉइंट गणना एक अलग कोप्रोसेसर के बिना x86 श्रृंखला के लिए सॉफ्टवेयर ("सॉफ्ट-फ्लोट") में की गई थी। जिनमें से सभी (एफपीयू) में पारलौकिक कार्य शामिल नहीं हैं (उदाहरण वेइटेक 3167)।
mctylr

1
क्या आप अधिक विशिष्ट हो सकते हैं? टेलर श्रृंखला का उपयोग करके एक "पॉलिश" कैसे होता है?
हांक

4
एक उत्तर को "चमकाने" के रूप में, मान लीजिए कि आप साइन और कोसाइन दोनों की गणना कर रहे हैं। माना कि आप एक बिंदु पर दोनों का सही मूल्य जानते हैं (जैसे CORDIC से) लेकिन पास के बिंदु पर मान चाहते हैं। फिर एक छोटे अंतर के लिए, आप टेलर सन्निकटन f (x + h) = f (x) + h f '(x) या f (x + h) = f (x) + h f' (x) लगा सकते हैं + h ^ 2 f '' (x) / 2।
जॉन डी। कुक

6
x86 / x64 चिप्स में साइन (fsin) की गणना के लिए एक विधानसभा निर्देश है, लेकिन यह निर्देश कभी-कभी काफी गलत होता है और इसलिए शायद ही कभी इसका उपयोग किया जाता है। देखें randomascii.wordpress.com/2014/10/09/... जानकारी के लिए। अधिकांश अन्य प्रोसेसर में साइन और कोजाइन के लिए निर्देश नहीं होते हैं क्योंकि सॉफ्टवेयर में उनकी गणना करने से अधिक लचीलापन मिलता है, और इससे भी तेज हो सकता है।
ब्रूस डावसन

3
इंटेल चिप्स के अंदर कॉर्डिक सामान आमतौर पर उपयोग नहीं किया जाता है। सबसे पहले, ऑपरेशन की सटीकता और संकल्प कई अनुप्रयोगों के लिए अत्यंत महत्वपूर्ण है। जब आप 7 वें अंक पर पहुंचते हैं, और अप्रत्याशित होता है, तो कॉर्डिक कुख्यात है। दूसरे, मैंने सुना है कि उनके कार्यान्वयन में एक बग है, जो और भी अधिक समस्याओं का कारण बनता है। मैंने linux gcc के लिए पाप फ़ंक्शन पर एक नज़र डाली, और निश्चित रूप से पर्याप्त है, यह chebyshev का उपयोग करता है। अंतर्निहित सामान का उपयोग नहीं किया जाता है। ओह, इसके अलावा, चिप में कॉर्डिक एल्गोरिथ्म सॉफ्टवेयर समाधान की तुलना में धीमा है।
डोनाल्ड मुरैना

63

ठीक है किडिज़, पेशेवरों के लिए समय .... यह अनुभवहीन सॉफ्टवेयर इंजीनियरों के साथ मेरी सबसे बड़ी शिकायतों में से एक है। वे स्क्रैच (टेलर की श्रृंखला का उपयोग करके) से पारलौकिक कार्यों की गणना में आते हैं जैसे कि किसी ने भी अपने जीवन में पहले इन गणनाओं को नहीं किया था। सच नहीं। यह एक अच्छी तरह से परिभाषित समस्या है और बहुत ही चतुर सॉफ्टवेयर और हार्डवेयर इंजीनियरों द्वारा हजारों बार संपर्क किया गया है और इसका एक अच्छा परिभाषित समाधान है। मूल रूप से, अधिकांश ट्रान्सेंडैंटल फ़ंक्शंस चेबीशेव पॉलिनॉमिअल्स का उपयोग करके उनकी गणना करते हैं। किन पॉलिनेम्स का उपयोग किया जाता है यह परिस्थितियों पर निर्भर करता है। सबसे पहले, इस मामले पर बाइबिल हार्ट और चेनी द्वारा "कंप्यूटर अनुमोदन" नामक एक पुस्तक है। उस पुस्तक में, आप यह तय कर सकते हैं कि आपके पास एक हार्डवेयर योजक, गुणक, विभक्त, आदि हैं और यह तय करें कि कौन से ऑपरेशन सबसे तेज़ हैं। उदा। यदि आपके पास वास्तव में तेज़ विभक्त था, साइन की गणना करने का सबसे तेज़ तरीका P1 (x) / P2 (x) हो सकता है, जहाँ P1, P2 Chebyshev polynomials हैं। तेजी से विभक्त के बिना, यह सिर्फ पी (एक्स) हो सकता है, जहां पी में पी 1 या पी 2 की तुलना में बहुत अधिक शब्द हैं .... इसलिए यह धीमा होगा। तो, पहला कदम अपने हार्डवेयर को निर्धारित करना है और यह क्या कर सकता है। फिर आप उदाहरण के लिए कोसाइन के लिए चेबीशेव पॉलिनॉमिअल्स (जो कि आमतौर पर कॉशन (कुल्हाड़ी) = aP (x) का उपयुक्त संयोजन चुनते हैं, फिर से P एक Chebyshev बहुपद है)। फिर आप तय करें कि आपको कौन सी दशमलव परिशुद्धता चाहिए। उदाहरण के लिए यदि आप 7 अंक सटीक चाहते हैं, तो आप उस पुस्तक में उपयुक्त तालिका में देखते हैं, और यह आपको (सटीक = 7.33 के लिए) एक नंबर N = 4 और एक बहुपद संख्या 3502 देगी। N ​​का क्रम है बहुपद (इसलिए यह p4.x ^ 4 + p3.x ^ 3 + P2.x ^ 2 + p1.x + p0) है, क्योंकि N = 4। फिर आप पी 4, पी 3, पी 2, पी 1, का वास्तविक मूल्य देखें। 350 के तहत पुस्तक के पीछे p0 मान (वे फ्लोटिंग पॉइंट में होंगे)। फिर आप सॉफ़्टवेयर में अपने एल्गोरिथ्म को फॉर्म में लागू करते हैं: (((p4.x + p3) .x + P2) .x + p1) .x + p0 .... और यह है कि आप 7 दशमलव कोसाइन की गणना करेंगे उस हार्डवेयर पर स्थान।

ध्यान दें कि एफपीयू में ट्रान्सेंडैंटल ऑपरेशन के अधिकांश हार्डवेयर कार्यान्वयन में आमतौर पर कुछ माइक्रोकोड और ऑपरेशन शामिल होते हैं (हार्डवेयर पर निर्भर करता है)। Chebyshev बहुपद का उपयोग अधिकांश ट्रान्सेंडेंटल के लिए किया जाता है लेकिन सभी में नहीं। उदाहरण के लिए स्क्वायर रूट पहले लुकअप टेबल का उपयोग करके न्यूटन रैपसन विधि के दोहरे पुनरावृत्ति का उपयोग करने के लिए तेज़ है। फिर, वह पुस्तक "कंप्यूटर अनुमोदन" आपको बताएगा।

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

अब, कहा जा रहा है कि ऐसी तकनीकें हैं, जिसके तहत चेबीशेव बहुपद का उपयोग कम डिग्री बहुपद के साथ एकल परिशुद्धता परिणाम प्राप्त करने के लिए किया जा सकता है (जैसे कोसाइन के लिए उदाहरण)। फिर, बहुत बड़ी बहुपद में जाने के लिए सटीकता को बढ़ाने के लिए मूल्यों के बीच हस्तक्षेप करने के लिए अन्य तकनीकें हैं, जैसे "गैल की सटीक सारणी विधि"। यह बाद की तकनीक है जो एसीएम साहित्य के संदर्भ में पोस्ट का जिक्र है। लेकिन अंततः, चेबिशेव पॉलिनॉमिअल्स का उपयोग किया जाता है जो वहां 90% प्राप्त करते हैं।

का आनंद लें।


6
मैं पहले कुछ वाक्यों से अधिक सहमत नहीं हो सका। इसके अलावा, यह याद रखने योग्य है कि गारंटीकृत परिशुद्धता के साथ विशेष कार्यों की गणना एक कठिन समस्या है । जिन चतुर लोगों का आप उल्लेख करते हैं, वे अपना अधिकांश जीवन ऐसा करने में व्यतीत करते हैं। इसके अलावा, एक अधिक तकनीकी नोट पर, मिन-मैक्स बहुपद की मांग के बाद की जाने वाली कब्र हैं, और चेबीशेव पॉलिनॉमिअल्स उनके लिए अधिक सरल हैं।
अलेक्जेंड्रे सी।

161
-1 अनप्रोफेशनल और रंबिंग (और हल्के से कठोर) टोन के लिए, और इस तथ्य के लिए कि इस उत्तर की वास्तविक गैर-बेमानी सामग्री , जुए और कृपालुता से छीन ली गई, मूल रूप से यह उबलता है "वे अक्सर चेयशेव पॉलिनॉमिअल्स का उपयोग करते हैं; इस पुस्तक को देखें अधिक जानकारी के लिए, यह वास्तव में अच्छा है! " जो, आप जानते हैं, अच्छी तरह से पूरी तरह से सही हो सकता है, लेकिन यह वास्तव में एसओ पर यहां हम चाहते हैं कि स्वयं के जवाब की तरह नहीं है । इस तरह से नीचे संक्षेप में, यह सवाल पर एक सभ्य टिप्पणी की है, हालांकि होगा।
इल्मरी करोनन

2
प्रारंभिक खेल के विकास के वर्षों में, यह आमतौर पर लुकअप तालिकाओं के साथ किया गया था जो गति के लिए महत्वपूर्ण हैं)। हम आम तौर पर उन चीजों के लिए मानक काम नहीं करता था।
टॉप्सपिन

4
मैं एम्बेडेड सिस्टम में लुकअप तालिकाओं का उपयोग अक्सर और बिटियंस (रेडियंस के बजाय) करता हूं, लेकिन यह एक विशेष एप्लिकेशन (आपके गेम की तरह) के लिए है। मुझे लगता है कि आदमी को इस बात में दिलचस्पी है कि कैसे सी संकलक फ्लोटिंग पॉइंट नंबरों के लिए पाप की गणना करता है ....
डोनाल्ड मरे

1
आह, 50 साल पहले। मैंने मैकलेरन सीरीज़ के साथ बरोज़ B220 पर ऐसे खेलना शुरू किया। बाद में सीडीसी हार्डवेयर और फिर मोटोरोला 68000। आर्किन गड़बड़ था - मैंने इष्टतम गुणांक खोजने के लिए दो बहुपद और विकसित कोड के भागफल को चुना।
रिक जेम्स

15

के लिए sinविशेष रूप से, टेलर विस्तार का उपयोग आप प्रदान करेगा:

sin (x): = x - x ^ 3/3! + x ^ 5/5! - x ^ 7/7! + ... (1)

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

float sin(float x)
{
  float res=0, pow=x, fact=1;
  for(int i=0; i<5; ++i)
  {
    res+=pow/fact;
    pow*=-1*x*x;
    fact*=(2*(i+1))*(2*(i+1)+1);
  }

  return res;
}

नोट: (1) छोटे कोणों के लिए अनुत्पादक पाप (x) = x के कारण काम करता है। बड़े कोणों के लिए आपको स्वीकार्य परिणाम प्राप्त करने के लिए अधिक से अधिक शब्दों की गणना करने की आवश्यकता है। आप कुछ समय तर्क का उपयोग कर सकते हैं और एक निश्चित सटीकता के लिए जारी रख सकते हैं:

double sin (double x){
    int i = 1;
    double cur = x;
    double acc = 1;
    double fact= 1;
    double pow = x;
    while (fabs(acc) > .00000001 &&   i < 100){
        fact *= ((2*i)*(2*i+1));
        pow *= -1 * x*x; 
        acc =  pow / fact;
        cur += acc;
        i++;
    }
    return cur;

}

1
यदि आप गुणांक को थोड़ा छोटा करते हैं (और उन्हें बहुपद में कोड करते हैं), तो आप लगभग 2 पुनरावृत्तियों को जल्द ही रोक सकते हैं।
रिक जेम्स

14

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

संख्यात्मक विधियाँ सटीकता की एक मनमानी मात्रा में कार्यों को अनुमानित कर सकती हैं और चूंकि आपके पास एक अस्थायी संख्या में सटीकता की मात्रा परिमित है, वे इन कार्यों को बहुत अच्छी तरह से सूट करते हैं।


12
एक वास्तविक कार्यान्वयन शायद टेलर श्रृंखला का उपयोग नहीं करेगा, क्योंकि अधिक कुशल तरीके हैं। आपको केवल [0 ... pi / 2] डोमेन में सही ढंग से अनुमानित करने की आवश्यकता है, और ऐसे कार्य हैं जो टेलर श्रृंखला की तुलना में अधिक कुशलता से एक अच्छा अनुमान प्रदान करेंगे।
डेविड थॉर्नले

2
@ डेविड: मैं सहमत हूं। मैं अपने जवाब में "जैसे" शब्द का उल्लेख करने के लिए पर्याप्त सावधान था। लेकिन टेलर विस्तार उन तरीकों के पीछे के विचार को समझाने के लिए एक सरल है जो लगभग कार्य करता है। उस ने कहा, मैंने सॉफ्टवेयर कार्यान्वयन को देखा है (निश्चित नहीं कि अगर उन्हें अनुकूलित किया गया था) जो टेलर श्रृंखला का उपयोग करता है।
मेहरदाद अफश्री

1
दरअसल, बहुपत्नी सन्निकटन त्रिकोणमितीय कार्यों की गणना करने के सबसे कुशल तरीकों में से एक हैं।
जेरेमी सलवेन

13

टेलर श्रृंखला का उपयोग करें और श्रृंखला की शर्तों के बीच संबंध खोजने की कोशिश करें ताकि आप बार-बार चीजों की गणना न करें

यहाँ cosinus के लिए एक उदाहरण है:

double cosinus(double x, double prec)
{
    double t, s ;
    int p;
    p = 0;
    s = 1.0;
    t = 1.0;
    while(fabs(t/s) > prec)
    {
        p++;
        t = (-t * x * x) / ((2 * p - 1) * (2 * p));
        s += t;
    }
    return s;
}

इसका उपयोग करके हम पहले से ही उपयोग किए गए राशि का नया शब्द प्राप्त कर सकते हैं (हम भाज्य और x 2p से बचते हैं )

व्याख्या


2
क्या आप जानते हैं कि आप TeX का उपयोग करके Google चार्ट API का उपयोग इस तरह के फॉर्मूले बनाने के लिए कर सकते हैं? code.google.com/apis/chart/docs/gallery/formulas.html
गाब रॉय

11

यह एक जटिल प्रश्न है। X86 परिवार के इंटेल जैसे सीपीयू में sin()फ़ंक्शन का हार्डवेयर कार्यान्वयन है , लेकिन यह x87 FPU का हिस्सा है और इसका उपयोग अब 64-बिट मोड (जहां SSE2 रजिस्टरों के बजाय उपयोग किया जाता है) में नहीं किया जाता है। उस मोड में, एक सॉफ्टवेयर कार्यान्वयन का उपयोग किया जाता है।

इस तरह के कई कार्यान्वयन हैं। एक fdlibm में है और जावा में उपयोग किया जाता है। जहां तक ​​मुझे पता है, ग्लिबक कार्यान्वयन में एफडीलिब के कुछ हिस्सों और आईबीएम द्वारा योगदान किए गए अन्य हिस्से शामिल हैं।

ट्रान्सेंडैंटल फ़ंक्शंस के सॉफ़्टवेयर कार्यान्वयन जैसे sin()आमतौर पर बहुपद द्वारा सन्निकटन का उपयोग करते हैं, अक्सर टेलर श्रृंखला से प्राप्त किया जाता है।


3
SSE2 रजिस्टरों का उपयोग पाप की गणना करने के लिए नहीं किया जाता है (), न तो x86 में और न ही x64 मोड में और निश्चित रूप से, पाप की गणना मोड की परवाह किए बिना हार्डवेयर में की जाती है। अरे, यह 2010 है हम में रहते हैं :)
इगोर Korkhov

7
@ आईओआरजी: यह इस बात पर निर्भर करता है कि आप किस गणित पुस्तकालय को देख रहे हैं। यह पता चला है कि x86 पर सबसे अधिक अनुकूलित गणित पुस्तकालय SSE सॉफ्टवेयर कार्यान्वयन के लिए उपयोग करते हैं sinऔर cosयह FPU पर हार्डवेयर निर्देशों की तुलना में तेज़ हैं। सरल, अधिक भोले पुस्तकालयों fsinऔर fcosनिर्देशों का उपयोग करते हैं ।
स्टीफन कैनन

@ स्टेफेन कैनन: क्या उन फास्ट लाइब्रेरियों में 80 बिट की शुद्धता होती है जैसा कि FPU रजिस्टर में होता है? मुझे इस बात पर बहुत संदेह है कि वे सटीकता पर गति का पक्ष लेते हैं, जो निश्चित रूप से कई परिदृश्यों में उचित है, उदाहरण के लिए खेलों में। और मुझे विश्वास है कि एसएसई और प्री-कॉम्प्लेक्लेटेड मध्यवर्ती तालिकाओं का उपयोग करके 32 बिट परिशुद्धता के साथ साइन की गणना FSINपूर्ण सटीकता के साथ उपयोग करने से तेज हो सकती है । मैं बहुत आभारी रहूंगा यदि आप मुझे उन तेज़ पुस्तकालयों के नाम बताते हैं, तो एक नज़र रखना दिलचस्प है।
इगोर कोर्खोव

@ आईओआरजी: 64-बिट मोड में x86 पर, कम से कम सभी यूनिक्स-जैसी प्रणालियों पर जिन्हें मैं जानता हूं, परिशुद्धता 64 बिट्स तक सीमित है, एक्स87 एफपीयू के 79 बिट्स नहीं। सॉफ्टवेयर कार्यान्वयन sin()लगभग दो बार होने की तुलना में तेजी से होता है fsin(ठीक है क्योंकि यह कम सटीकता के साथ किया जाता है)। ध्यान दें कि x87 अपने घोषित 79 बिट्स की तुलना में थोड़ा कम वास्तविक परिशुद्धता के लिए जाना जाता है।
थॉमस पोर्निन

1
दरअसल, msvc रनटाइम लाइब्रेरी में 32-बिट्स और 64-बिट्स पाप () दोनों के कार्यान्वयन FSIN निर्देश का उपयोग नहीं करते हैं। वास्तव में, वे अलग-अलग परिणाम देते हैं, उदाहरण के लिए पाप करते हैं (0.70444454416678126)। यह 32-बिट प्रोग्राम में 0.64761068800896837 (दाएं से 0.5 * (ईपीएस / 2) सहिष्णुता) के परिणामस्वरूप होगा, और 64-बिट में 0.64761068800896848 (गलत) में परिणाम होगा।
e.tadeu

9

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

कुछ मामलों में, अधिकतम त्रुटि वह नहीं है जो आप में रुचि रखते हैं, लेकिन अधिकतम सापेक्ष त्रुटि। साइन फ़ंक्शन के लिए उदाहरण के लिए, x = 0 के पास त्रुटि बड़े मानों की तुलना में बहुत छोटी होनी चाहिए; आप एक छोटी सापेक्ष त्रुटि चाहते हैं । इसलिए आप पाप x / x के लिए चेबीशेव बहुपद की गणना करेंगे, और उस बहुपद को x से गुणा करेंगे।

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

उदाहरण के लिए, पाप x = x - x ^ 3/6 + x ^ 5/120 - x ^ 7/5040 ... यदि आप भोली पाप x = x * (1 - x ^ 2/6 + x ^ 4 /) की गणना करते हैं १२० - x ^ ६ / ५०४० ...), तब कोष्ठक में वह कार्य कम हो रहा है, और यह होगा कि यदि y x की अगली बड़ी संख्या है, तो कभी-कभी पाप x पाप x से छोटा होगा। इसके बजाय, पाप x = x - x ^ 3 * (1/6 - x ^ 2/120 + x ^ 4/5040 ...) की गणना करें जहां ऐसा नहीं हो सकता है।

चेबीशेव पॉलिनॉमिअल्स की गणना करते समय, आपको आमतौर पर गुणकों को दोगुना सटीक करने के लिए गोल करना होगा, उदाहरण के लिए। लेकिन एक Chebyshev बहुपद इष्टतम है, जबकि डबल परिशुद्धता के लिए गुणांक के साथ Chebyshev बहुपद डबल परिशुद्धता गुणांक के साथ इष्टतम बहुपद नहीं है!

उदाहरण के लिए पाप (x), जहाँ आपको x, x ^ 3, x ^ 5, x ^ 7 आदि के लिए गुणांक की आवश्यकता होती है, आप निम्न कार्य करते हैं: एक बहुपद (ax + bx) + + के साथ sin x के सर्वश्रेष्ठ सन्निकटन की गणना करें। cx ^ 5 + dx ^ 7) दोगुनी से अधिक सटीकता के साथ, फिर ए टू डबल परिशुद्धता के लिए, ए। और ए के बीच का अंतर काफी बड़ा होगा। अब एक बहुपद (bx ^ 3 + cx ^ 5 + dx ^ 7) के साथ (sin x - Axe) के सर्वश्रेष्ठ सन्निकटन की गणना करें। आप अलग-अलग गुणांक प्राप्त करते हैं, क्योंकि वे ए और ए के बीच अंतर को डबल परिशुद्धता बी के अनुकूल करते हैं। फिर एक बहुपद cx ^ 5 + dx ^ 7 और इतने पर लगभग अनुमानित (पाप x - अक्ष - Bx ^ 3)। आपको एक बहुपद मिलेगा जो लगभग मूल चेबिशेव बहुपद के जितना अच्छा है, लेकिन चेबीशेव की तुलना में बेहतर डबल चक्कर लगाने के लिए बेहतर है।

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

यह सब आपको अंतिम बिट में 0.55 गुना अधिक आसानी से प्राप्त होगा, जहां +, -, *, / में अंतिम बिट में 0.50 गुना अधिक त्रुटि हो सकती है।


1
इस तरह से एक का एक अच्छा विवरण है हो सकता है sin (x) कुशलता से गणना, लेकिन यह वास्तव में ओ पी के सवाल का है, जो कि कैसे आम सी पुस्तकालयों / compilers के बारे में विशेष रूप से है जवाब देने के लिए नहीं प्रतीत होता है है यह गणना।
इल्मरी करोनन

Chebyshev बहुपद एक अंतराल पर अधिकतम निरपेक्ष मूल्य को कम करते हैं, लेकिन वे एक लक्ष्य फ़ंक्शन और बहुपद के बीच सबसे बड़े अंतर को कम नहीं करते हैं। मिनिमैक्स पोलीनॉमिअल्स ऐसा करते हैं।
एरिक पोस्टपिसिल

9

जैसे त्रिकोणमितीय समारोह के संबंध में sin(), cos(), tan()वहाँ, कोई जिक्र नहीं किया गया है, 5 साल के बाद उच्च गुणवत्ता ट्रिग कार्यों का एक महत्वपूर्ण पहलू की: रेंज कमी

इन कार्यों में से किसी एक में एक प्रारंभिक चरण, 2 * ians अंतराल की सीमा तक, रेडियन में कोण को कम करना है। लेकिन x = remainder(x, 2*M_PI)error तर्कहीन है, इसलिए साधारण त्रुटि जैसे कि त्रुटि M_PI, या मशीन पाई, π का ​​एक अनुमान है। तो, कैसे करें x = remainder(x, 2*π)?

प्रारंभिक पुस्तकालयों ने गुणवत्ता के परिणाम देने के लिए विस्तारित परिशुद्धता या तैयार की गई प्रोग्रामिंग का उपयोग किया लेकिन फिर भी सीमित सीमा तक double। जब एक बड़े मूल्य का अनुरोध किया गया था sin(pow(2,30)), तो परिणाम अर्थहीन थे या 0.0हो सकता है कि त्रुटि झंडे के साथ TLOSSसटीक की कुल हानि या सटीक नुकसान की तरह कुछ सेट किया गया हो PLOSS

बड़े मानों की अच्छी श्रेणी में कमी जैसे-reduction से values ​​एक चुनौतीपूर्ण समस्या है जो मूल ट्रिगर फ़ंक्शन की चुनौतियों को पसंद करती है sin(), जैसे कि , स्वयं।

एक अच्छी रिपोर्ट भारी दलीलों के लिए तर्क में कमी है: गुड टू द लास्ट बिट (1992)। यह मुद्दा अच्छी तरह से शामिल किया गया है: जरूरत पर चर्चा करता है और कैसे चीजें विभिन्न प्लेटफार्मों (स्पार्क, पीसी, एचपी, 30+ अन्य) पर थे और एक समाधान एल्गोरिथ्म के लिए गुणवत्ता के परिणाम देता है प्रदान करता है सब double से -DBL_MAXकरने के लिए DBL_MAX


यदि मूल तर्क डिग्री में हैं, फिर भी एक बड़े मूल्य का हो सकता है, fmod()पहले से बेहतर सुधार के लिए उपयोग करें । एक अच्छा कोई त्रुटि नहींfmod() शुरू करेगा और इसलिए उत्कृष्ट श्रेणी में कमी प्रदान करेगा।

// sin(degrees2radians(x))
sin(degrees2radians(fmod(x, 360.0))); // -360.0 < fmod(x,360) < +360.0

विभिन्न ट्रिगर पहचान और remquo()भी अधिक सुधार प्रदान करते हैं। नमूना: सिंद ()


6

पुस्तकालय कार्यों का वास्तविक कार्यान्वयन विशिष्ट संकलक और / या पुस्तकालय प्रदाता तक है। चाहे वह हार्डवेयर या सॉफ्टवेयर में किया गया हो, चाहे वह टेलर का विस्तार हो या नहीं, आदि अलग-अलग होंगे।

मुझे पता है कि बिल्कुल कोई मदद नहीं है।


5

वे आम तौर पर सॉफ्टवेयर में कार्यान्वित होते हैं और ज्यादातर मामलों में संबंधित हार्डवेयर (यानी, एसेफ़ॉर्म) कॉल का उपयोग नहीं करेंगे। हालांकि, जैसा कि जेसन ने बताया, ये विशिष्ट रूप से लागू हो रहे हैं।

ध्यान दें कि ये सॉफ़्टवेयर रूट कंपाइलर स्रोतों का हिस्सा नहीं हैं, बल्कि यह GNU कंपाइलर के लिए क्लिबिंग, या ग्लिबेक जैसे कंपोस्टिंग लाइब्रेरी में मिलेगा। Http://www.gnu.org/software/libc/manual/html_mono/libc.html#Trig-Functions देखें

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


5

यदि आप सॉफ़्टवेयर में कार्यान्वयन चाहते हैं, हार्डवेयर नहीं, तो इस प्रश्न के निश्चित उत्तर की तलाश करने का स्थान न्यूमेरिकल व्यंजनों का अध्याय 5 है । मेरी प्रतिलिपि एक बॉक्स में है, इसलिए मैं विवरण नहीं दे सकता, लेकिन संक्षिप्त संस्करण (यदि मुझे यह अधिकार याद है) तो यह है कि आप tan(theta/2)अपने आदिम संचालन के रूप में लेते हैं और वहां से दूसरों की गणना करते हैं। गणना श्रृंखला सन्निकटन के साथ की जाती है, लेकिन यह एक ऐसी चीज है जो टेलर श्रृंखला की तुलना में बहुत अधिक तेजी से परिवर्तित होती है

क्षमा करें, मैं पुस्तक पर अपना हाथ डाले बिना अधिक याद नहीं कर सकता।


5

स्रोत से टकराने और यह देखने के लिए ऐसा कुछ नहीं है कि किसी व्यक्ति ने वास्तव में एक पुस्तकालय में इसका उपयोग कैसे किया है; आइए विशेष रूप से एक सी लाइब्रेरी कार्यान्वयन को देखें। मैंने uLibC को चुना।

यहाँ पाप कार्य है:

http://git.uclibc.org/uClibc/tree/libm/s_sin.c

ऐसा लगता है कि यह कुछ विशेष मामलों को संभालता है, और फिर कुछ इनपुट को कम करने के लिए रेंज [- -64 / 4, pi / 4] तक इनपुट को मैप करता है, (तर्क को दो भागों में विभाजित करता है, एक बड़ा हिस्सा और एक पूंछ) फोन करने से पहले

http://git.uclibc.org/uClibc/tree/libm/k_sin.c

जो तब उन दो भागों पर काम करता है। यदि कोई पूंछ नहीं है, तो एक अनुमानित उत्तर डिग्री की बहुपद का उपयोग करके उत्पन्न होता है 13. यदि कोई पूंछ है, तो आपको उस सिद्धांत के आधार पर एक छोटा सुधारात्मक जोड़ मिलेगाsin(x+y) = sin(x) + sin'(x')y


4

जब भी इस तरह के फ़ंक्शन का मूल्यांकन किया जाता है, तो कुछ स्तर पर या तो सबसे अधिक संभावना होती है:

  • मूल्यों की एक तालिका जो प्रक्षेपित होती है (तेज, गलत अनुप्रयोगों के लिए - जैसे कंप्यूटर ग्राफिक्स)
  • एक श्रृंखला के मूल्यांकन कि वांछित मूल्य --- शायद करने के लिए और converges नहीं Clenshaw-कर्टिस की तरह एक फैंसी क्षेत्रकलन के आधार पर एक टेलर श्रृंखला, अधिक संभावना है कि कुछ और।

यदि कोई हार्डवेयर समर्थन नहीं है, तो कंपाइलर बाद के तरीके का उपयोग करता है, केवल असेम्बलर कोड (बिना डिबग प्रतीकों के साथ) का उपयोग करके, एसी लाइब्रेरी का उपयोग करने के बजाय --- आपके डीबगर में वास्तविक कोड को ट्रैक करने के लिए आपके लिए यह मुश्किल बना देता है।


4

जैसा कि कई लोगों ने बताया, यह कार्यान्वयन पर निर्भर है। लेकिन जहां तक ​​मैं आपके प्रश्न को समझता हूं, आप गणित कार्यों के एक वास्तविक सॉफ्टवेयर कार्यान्वयन में रुचि रखते थे , लेकिन सिर्फ एक को खोजने के लिए प्रबंधन नहीं किया। अगर ऐसा है तो यहाँ आप हैं:

  • Http://ftp.gnu.org/gnu/glibc/ से glibc स्रोत कोड डाउनलोड करें
  • अनपैक्ड ग्लिबैक रूट \ sysdeps \ ieee754 \ dbl-64 फ़ोल्डर dosincos.cमें स्थित फ़ाइल को देखें
  • इसी तरह आप बाकी गणित पुस्तकालय के कार्यान्वयन पा सकते हैं, बस उपयुक्त नाम वाली फ़ाइल की तलाश करें

आपके पास .tblएक्सटेंशन वाली फ़ाइलों पर एक नज़र भी हो सकती है , उनकी सामग्री द्विआधारी रूप में विभिन्न कार्यों के पूर्व- निर्मित मानों की विशाल तालिका से अधिक कुछ नहीं है । यही कारण है कि कार्यान्वयन इतना तेज़ है: जो भी श्रृंखला वे उपयोग करते हैं उनके सभी गुणांक की गणना करने के बजाय वे बस एक त्वरित खोज करते हैं, जो बहुत तेज़ है। BTW, वे साइन और कोसाइन की गणना करने के लिए दर्जी श्रृंखला का उपयोग करते हैं।

आशा है कि ये आपकी मदद करेगा।


4

मैं sin()एक वर्तमान x86 प्रोसेसर पर जीसीसी के सी संकलक के साथ संकलित सी कार्यक्रम के मामले में जवाब देने की कोशिश करूंगा (आइए एक इंटेल कोर 2 डुओ कहते हैं)।

सी भाषा में स्टैंडर्ड सी लाइब्रेरी आम गणित काम करता है, अपने आप में भाषा में नहीं शामिल शामिल हैं (उदाहरण के लिए pow, sinऔर cosशक्ति, साइन, और कोज्या के लिए क्रमशः)। जिनमें से प्रमुखों को math.h में शामिल किया गया है ।

अब एक GNU / Linux सिस्टम पर, ये लाइब्रेरी फ़ंक्शंस glibc (GNU libc या GNU C लाइब्रेरी) द्वारा प्रदान किए जाते हैं। लेकिन जीसीसी संकलक आपको गणित पुस्तकालय ( libm.so) -lmको इन गणित कार्यों के उपयोग को सक्षम करने के लिए संकलक ध्वज का उपयोग करके लिंक करना चाहता है । मुझे यकीन नहीं है कि यह मानक सी लाइब्रेरी का हिस्सा क्यों नहीं है। ये फ़्लोटिंग पॉइंट फ़ंक्शंस का सॉफ़्टवेयर संस्करण होगा, या "सॉफ्ट-फ़्लोट"।

एक तरफ: गणित के कार्यों के अलग होने का कारण ऐतिहासिक है, और इसका उद्देश्य केवल बहुत पुराने यूनिक्स प्रणालियों में निष्पादन योग्य कार्यक्रमों के आकार को कम करना था , संभवतः इससे पहले कि साझा पुस्तकालय उपलब्ध थे, जहां तक ​​मुझे पता है।

अब कंपाइलर अपने सीपीयू / एफपीयू के बिल्ट-इन पाप () फंक्शन में एक देशी निर्देश के लिए कॉल के साथ प्रतिस्थापित करने के लिए मानक सी लाइब्रेरी फ़ंक्शन sin()(द्वारा प्रदान की गई libm.so) को अनुकूलित कर सकता है , जो कि एफपीयू इंस्ट्रक्शन ( FSINx86 / x87 के लिए) के रूप में मौजूद है कोर 2 श्रृंखला जैसे नए प्रोसेसर (यह i486DX के रूप में बहुत पीछे तक सही है)। यह gcc संकलक को दिए गए अनुकूलन झंडे पर निर्भर करेगा। यदि संकलक को कोड लिखने के लिए कहा गया था जो किसी भी i386 या नए प्रोसेसर पर निष्पादित होगा, तो यह ऐसा अनुकूलन नहीं करेगा। -mcpu=486झंडा संकलक को सूचित किया है कि यह इस तरह के एक अनुकूलन बनाने के लिए सुरक्षित था।

अब यदि प्रोग्राम पाप के सॉफ़्टवेयर संस्करण () फ़ंक्शन को निष्पादित करता है, तो यह एक CORDIC (कोऑर्डिनेट रोटेशन DIgital कंप्यूटर) या BKM एल्गोरिथ्म पर आधारित होगा , या अधिक संभावना एक टेबल या पॉवर-सीरीज़ की गणना जो आमतौर पर अब गणना करने के लिए उपयोग की जाती है। ऐसे पारलौकिक कार्य। [Src: http://en.wikipedia.org/wiki/Cordic#Application]

किसी भी हाल ही में (2.9x के बाद से।) जीसीसी का संस्करण भी बिल्ट-इन संस्करण प्रदान करता है, __builtin_sin()जिसका उपयोग सी लाइब्रेरी संस्करण में मानक कॉल को अनुकूलन के रूप में बदलने के लिए किया जाएगा।

मुझे यकीन है कि यह कीचड़ के रूप में स्पष्ट है, लेकिन उम्मीद है कि आप अपेक्षा से अधिक जानकारी देते हैं, और अपने आप को सीखने के लिए बहुत से कूदने के बिंदु।



3

टेलर श्रृंखला का उपयोग न करें। जैसा कि ऊपर के कुछ लोगों द्वारा बताया गया है, चेबिशेव बहुपद दोनों ही अधिक तेज और सटीक हैं। यहाँ एक कार्यान्वयन है (मूल रूप से ZX स्पेक्ट्रम रॉम से): https://albertveli.wordpress.com/2015/01/10/zx-sine/


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

1
आह, तुम सही हो। यह एक टिप्पणी होना चाहिए था और जवाब नहीं। मैंने कुछ समय में SO का उपयोग नहीं किया है और यह भूल गया कि सिस्टम कैसे काम करता है। वैसे भी, मुझे लगता है कि स्पेक्ट्रम कार्यान्वयन प्रासंगिक है क्योंकि इसमें वास्तव में धीमा सीपीयू था और गति सार थी। सबसे अच्छा एल्गोरिथ्म तो निश्चित रूप से अभी भी बहुत अच्छा है इसलिए यह सी पुस्तकालयों के लिए एक अच्छा विचार होगा कि चेबीशेव पॉलिनॉमिअल्स का उपयोग करके ट्रिगर कार्यों को लागू करें।
अल्बर्ट वेली

2

टेलर श्रृंखला का उपयोग करके कोड के माध्यम से करना साइन / कोसाइन / स्पर्शरेखा की गणना करना वास्तव में बहुत आसान है। खुद को लिखना 5 सेकंड की तरह लगता है।

इस समीकरण के साथ पूरी प्रक्रिया को यहाँ प्रस्तुत किया जा सकता है:

पाप और लागत विस्तार

यहाँ कुछ दिनचर्याएँ हैं जो मैंने C के लिए लिखी हैं:

double _pow(double a, double b) {
    double c = 1;
    for (int i=0; i<b; i++)
        c *= a;
    return c;
}

double _fact(double x) {
    double ret = 1;
    for (int i=1; i<=x; i++) 
        ret *= i;
    return ret;
}

double _sin(double x) {
    double y = x;
    double s = -1;
    for (int i=3; i<=100; i+=2) {
        y+=s*(_pow(x,i)/_fact(i));
        s *= -1;
    }  
    return y;
}
double _cos(double x) {
    double y = 1;
    double s = -1;
    for (int i=2; i<=100; i+=2) {
        y+=s*(_pow(x,i)/_fact(i));
        s *= -1;
    }  
    return y;
}
double _tan(double x) {
     return (_sin(x)/_cos(x));  
}

4
यह एक बुरा कार्यान्वयन है क्योंकि यह उपयोग नहीं करता है कि साइन और कोसाइन श्रृंखला के क्रमिक शब्दों में बहुत सरल उद्धरण हैं। जिसका अर्थ है कि व्यक्ति O (n ^ 2) से गुणा और विभाजनों की संख्या को घटाकर O (n) कर सकता है। उदाहरण के लिए बीसी (पोसिक्स मल्टीप्रेचर कैलकुलेटर) गणित पुस्तकालय में किया जाता है।
लुत्ज लेहमन 23

2
यह भी इस सवाल का जवाब देने के लिए नहीं लगता है के रूप में पूछा; ओपी पूछ रहा है कि ट्रिम फ़ंक्शंस की गणना आम सी कंपाइलर्स / लाइब्रेरीज़ द्वारा की जाती है, कस्टम रीइम्प्लीमेंटेशन के लिए नहीं।
इल्मरी करोनें

2
मुझे लगता है कि यह एक अच्छा जवाब है क्योंकि यह उस सवाल की भावना का जवाब देता है जो (और मैं केवल पाठ्यक्रम का अनुमान लगा सकता हूं) पाप की तरह एक अन्यथा "ब्लैक बॉक्स" फ़ंक्शन के बारे में जिज्ञासा। यह यहाँ एकमात्र उत्तर है जो किसी को कुछ अनुकूलित सी सोर्स कोड पढ़ने के बजाय इसे कुछ ही सेकंड में चमकाने के द्वारा जल्दी से समझने का मौका देता है।
माइक एम

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


0

ब्लाइंडी के उत्तर से कोड का बेहतर संस्करण

#define EPSILON .0000000000001
// this is smallest effective threshold, at least on my OS (WSL ubuntu 18)
// possibly because factorial part turns 0 at some point
// and it happens faster then series element turns 0;
// validation was made against sin() from <math.h>
double ft_sin(double x)
{
    int k = 2;
    double r = x;
    double acc = 1;
    double den = 1;
    double num = x;

//  precision drops rapidly when x is not close to 0
//  so move x to 0 as close as possible
    while (x > PI)
        x -= PI;
    while (x < -PI)
        x += PI;
    if (x > PI / 2)
        return (ft_sin(PI - x));
    if (x < -PI / 2)
        return (ft_sin(-PI - x));
//  not using fabs for performance reasons
    while (acc > EPSILON || acc < -EPSILON)
    {
        num *= -x * x;
        den *= k * (k + 1);
        acc = num / den;
        r += acc;
        k += 2;
    }
    return (r);
}

0

यह कैसे करता है इसका सार गेराल्ड व्हीटली द्वारा एप्लाइड न्यूमेरिकल एनालिसिस के इस अंश में निहित है :

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

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


-1

अगर तुम चाहो sinतो

 __asm__ __volatile__("fsin" : "=t"(vsin) : "0"(xrads));

अगर तुम चाहो cosतो

 __asm__ __volatile__("fcos" : "=t"(vcos) : "0"(xrads));

अगर तुम चाहो sqrtतो

 __asm__ __volatile__("fsqrt" : "=t"(vsqrt) : "0"(value));

तो मशीन के निर्देश क्या करेंगे तो गलत कोड का उपयोग क्यों करें?


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