2009-06-30 10 views
11

क्या संकलन समय पर पाउ ​​(10, x) की गणना करना संभव है?क्या मैं सी में संकलन-समय पर पाउ ​​(10, x) की गणना कर सकता हूं?

मुझे फ्लोटिंग पॉइंट समर्थन और धीमी पूर्णांक विभाजन के बिना प्रोसेसर मिला है। मैं संकलन समय पर जितनी संभव हो उतनी गणना करने की कोशिश कर रहा हूं। अगर मैं x और C/pow(10,x) दोनों तर्कों के रूप में पास करता हूं (एक्स और सी हमेशा स्थिर पूर्णांक होते हैं, लेकिन वे प्रत्येक कॉल के लिए अलग-अलग स्थिरांक होते हैं) तो मैं नाटकीय रूप से एक विशेष कार्य को गति दे सकता हूं। मैं सोच रहा हूं कि क्या मैं इन फ़ंक्शन को मैक्रो को पेश करके कम त्रुटि प्रवण कर सकता हूं जो प्रोग्रामर को इसकी गणना करने के लिए स्वचालित रूप से 1/pow(10,x) करता है?

क्या कोई प्री-प्रोसेसर चाल है? क्या मैं लाइब्रेरी कॉल को संकलित करने के लिए संकलक को मजबूर कर सकता हूं?

+0

मेरा मानना ​​है कि मैंने सबूत देखा है कि सी प्रीप्रोसेसर पूर्ण ट्यूरिंग कर रहा है (मुझे लगता है कि यह प्रीप्रोसेसर में एक अपरिवर्तित सी प्रतियोगिता में लागू एक टेप मशीन थी।) तो एक तरीका है। पता नहीं कि वह तरीका क्या है, यद्यपि। –

+0

प्रीप्रोसेसर # डिफाईन्स रिकर्सिव नहीं हो सकते हैं, क्योंकि वे केवल टेक्स्ट प्रतिस्थापन हैं। तो ग्रेग की तरह, यहां एक जगह है जो आपके समय को देखने में व्यतीत नहीं करती है। :) –

+0

@ ग्रेग डी: हालांकि, एक ट्यूरिंग मशीन से शुरू करना और 10 फ़ंक्शन के एक्सपोनेंट को लागू करने से मुझे महत्वाकांक्षी लगता है। –

उत्तर

8

आप फ्लोटिंग पॉइंट मानों के लिए वैज्ञानिक नोटेशन का उपयोग कर सकते हैं जो सी भाषा का हिस्सा है।ऐसा नहीं है कि तरह लग रहा है:

e = 1.602E-19 // == 1.602 * pow(10, -19) 

E से पहले नंबर (E शायद राजधानी या छोटे 1.602e-19) अंश हिस्सा है जहां के रूप में (हस्ताक्षरित) E के बाद अंकों अनुक्रम प्रतिपादक हिस्सा है। डिफ़ॉल्ट रूप से संख्या double प्रकार है, लेकिन यदि आप float या long double की आवश्यकता है तो आप एक फ़्लोटिंग पॉइंट प्रत्यय (f, F, l या L) संलग्न कर सकते हैं।

मैं एक मैक्रो में इस अर्थ पैक करने के लिए सिफारिश नहीं होगा:

  1. यह चर के लिए काम नहीं करेगा चल बिन्दु मूल्यों, आदि
  2. वैज्ञानिक संकेतन अधिक पठनीय है।
+5

यद्यपि आप इसकी अनुशंसा नहीं करते हैं, यह वही है जो मुझे चाहिए: '# परिभाषित पी 10 (एक्स) (1eX)', 'define fixedpt (मान, अंक) ((मान) * (1 << 15) के साथ संयुक्त/पी 10 (अंक)) 'मुझे वह परिणाम देता है जो मैं चाहता था, ऑप्टिमाइज़ेशन सेटिंग्स पर कोई निर्भरता नहीं। – AShelly

+0

कौन सा कंपाइलर '# परिभाषित पी 10 (एक्स) (1eX)' के साथ काम करता है? Arduino संकलक में, मुझे '# परिभाषित पी 10 (एक्स) (1e ## एक्स)' की आवश्यकता थी। – BigBobby

20

आपके अतिप्रवाह int (या यहां तक ​​कि लंबे) से पहले बहुत कम मूल्य संभव हैं। स्पष्टता के लिए, इसे एक टेबल बनाओ!

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

+1

प्रेरित! ज्ञात आधार की शक्तियों के लिए। यह दशमलव नहीं हैं। :) –

+0

सी और एक्स इस तरह से संबंधित हैं कि हम अतिप्रवाह नहीं होंगे: एक मान v दिया गया है, x चुना गया है ताकि 0.1 <= v/pow (10, x) <1, और C 32768 पर सेट हो * वी। – AShelly

+0

जो आप कहना चाहते थे वह है 'कुल = (कुल << 1) + (कुल << 3)' और जब आप 'कुल * = 10' – leiz

1

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

19

जीसीसी पर्याप्त उच्च अनुकूलन स्तर पर यह करेगा (-O1 यह मेरे लिए करता है)। उदाहरण के लिए:

#include <math.h> 

int test() { 
     double x = pow(10, 4); 
     return (int)x; 
} 

-O1 -m32 करने पर संकलित:

 .file "test.c" 
     .text 
.globl test 
     .type test, @function 
test: 
     pushl %ebp 
     movl %esp, %ebp 
     movl $10000, %eax 
     popl %ebp 
     ret 
     .size test, .-test 
     .ident "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3" 
     .section  .note.GNU-stack,"",@progbits 

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

+3

अच्छा। मैं सोच रहा हूं कि कैसे वे जांचते हैं कि पाउ एक शुद्ध कार्य है या उचित संकलन समय में नहीं है। हो सकता है कि उनके पास ज्ञात कार्यों की एक सूची है जो ऐसा हैं? – akappa

+0

गणित कार्यों में से कुछ सबसे अधिक संकलित कंपाइलर हैं; भी, जीसीसी के पास – Christoph

+0

'शुद्ध' के लिए गैर-मानक 'शुद्ध' विशेषता है, इस प्रकार के क्रॉस-संकलन इकाई अनुकूलन के लिए पर्याप्त नहीं है; और यदि वे एक ही संकलन इकाई में हैं तो इनलाइनिंग के बाद जीसीसी लगातार फोल्डिंग करेगा। शुद्ध ज्यादातर संकलक के लिए एक संकेत है कि इसे अपने रजिस्टरों में डेटा को अमान्य करने की आवश्यकता नहीं है। – bdonlan

10

आप Boost.Preprocessor साथ यह कर सकते हैं:

http://www.boost.org/doc/libs/1_39_0/libs/preprocessor/doc/index.html

कोड: जीसीसी के

#include <boost/preprocessor/repeat.hpp> 

#define _TIMES_10(z, n, data) * 10 
#define POW_10(n) (1 BOOST_PP_REPEAT(n, _TIMES_10, _)) 

int test[4] = {POW_10(0), POW_10(1), POW_10(2), POW_10(3)}; 
+1

को छायांकित करने वाले स्थानीय फ़ंक्शन पॉइंटर्स की संभावना से निपटना होगा दुर्भाग्य से मैं केवल सी का उपयोग कर रहा हूं। – AShelly

+1

हालांकि ओपी ने सी समाधान के लिए कहा, और बूस्ट एक सी ++ लाइब्रेरी – DaveR

+5

है लेकिन आप इसे सी (बूस्ट.प्रप्रोसेसर लाइब्रेरी) के साथ उपयोग कर सकते हैं, यह केवल प्रीप्रोसेसर है, मैंने इसे चेक किया है;) केवल अपनी निर्देशिका शामिल करें और इसे शामिल करें! –

3

हाल संस्करणों (4.3 के आसपास) जीएमपी और MPFR उपयोग करने के लिए कुछ करने की क्षमता जोड़ा निरंतर जटिल कार्यों का मूल्यांकन करके संकलन-समय अनुकूलन। वह दृष्टिकोण आपके कोड को सरल और पोर्टेबल छोड़ देता है, और भारी उठाने के लिए संकलक पर भरोसा करता है।

बेशक, यह करने के लिए सीमाएं हैं कि यह क्या कर सकता है। Here's a link to the description in the changelog, जिसमें फ़ंक्शंस की एक सूची शामिल है जो इस द्वारा समर्थित हैं। 'पाउ' एक है।

0

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

4

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

$ cat foo.c 
define(M4_POW_AUX, `ifelse($2, 1, $1, `eval($1 * M4_POW_AUX($1, decr($2)))')')dnl 
define(M4_POW, `ifelse($2, 0, 1, `M4_POW_AUX($1, $2)')')dnl 

#include <stdio.h> 

int      main(void) 
{ 
    printf("2^0 = %d\n", M4_POW(2, 0)); 
    printf("2^1 = %d\n", M4_POW(2, 1)); 
    printf("2^4 = %d\n", M4_POW(2, 4)); 

    return 0; 
} 

कमांड लाइन के लिए इस कोड नमूना मानक इनपुट से पढ़ने के लिए जीसीसी और एम 4 की क्षमता का उपयोग करता संकलित करने के लिए।

$ cat foo.c | m4 - | gcc -x c -o m4_pow - 
$ ./m4_pow 
2^0 = 1 
2^1 = 2 
2^4 = 16 

इस सहायता की आशा करें!

5

दरअसल, सी प्रीप्रोसेसर का शोषण करके, आप C pow(10, x) किसी वास्तविक C और अभिन्न x के लिए गणना कर सकते हैं। गौर करें कि, के रूप में @quinmars बताया गया है, सी आप वैज्ञानिक सिंटैक्स का उपयोग करने संख्यात्मक स्थिरांक व्यक्त करने के लिए अनुमति देता है:

#define myexp 1.602E-19 // == 1.602 * pow(10, -19) 

स्थिरांक के लिए प्रयोग की जाने वाली। मन, और चतुराई का एक सा में इस के साथ, हम एक पूर्वप्रक्रमक मैक्रो C और x लेता है का निर्माण और उन्हें एक घातांक टोकन में गठजोड़ कर सकते हैं:

#define EXP2(a, b) a ## b 
#define EXP(a, b) EXP2(a ## e,b) 
#define CONSTPOW(C,x) EXP(C, x) 

यह अब एक स्थिर संख्यात्मक मान के रूप में इस्तेमाल किया जा सकता:

const int myint = CONSTPOW(3, 4); // == 30000 
const double myfloat = CONSTPOW(M_PI, -2); // == 0.03141592653 
1

वहाँ only 23 different powers of 10 कि बिल्कुल प्रदर्शनीय डबल परिशुद्धता में तो आप बस एक लुकअप तालिका का उपयोग कर सकते कर सकते हैं

double POW10[] = {1., 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 
1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22}; 

यदि आपको सटीक मूल्य की आवश्यकता नहीं है, लेकिन 10 की बड़ी शक्तियों का उपयोग करने की आवश्यकता है तो आप केवल 10 की शक्तियों के अपने संस्करण लिख सकते हैं जो ऊपर की लुकअप तालिका का उपयोग करते हैं ताकि तुरंत 10 बार गुणा करने के बिना परिणाम प्राप्त हो सके। और फिर।

double pow10(int x) 
{ 
    if (x > 22) 
     return POW10[22]*pow10(x-22); 
    else if (x >= 0) 
     return POW10[x]; 
    else 
     return 1/pow10(-x); 
} 

यदि नकारात्मक घाटे की आवश्यकता नहीं है तो अंतिम शाखा को हटाया जा सकता है।

यदि स्मृति एक बाधा है तो आप लुकअप टेबल आकार को और भी कम कर सकते हैं। उदाहरण के लिए केवल 10 की शक्तियों को संग्रहित करके और 10 से गुणा करके जब एक्सपोनेंट अजीब है, तो तालिका का आकार अब केवल आधा है।

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