2012-08-05 29 views
5

मैं ऐसे प्रोजेक्ट पर काम कर रहा हूं जिसे FORTRAN में कुछ संख्यात्मक तरीकों को लागू करने की आवश्यकता है। इसके लिए, मुझे कुछ पुनरावर्ती कार्यों को लिखने की जरूरत है। मेरा कोड यहाँ है।FORTRAN फ़ंक्शन

!  
! File: main.F95 
! 

RECURSIVE FUNCTION integrate(n) RESULT(rv) 
    IMPLICIT NONE 
    DOUBLE PRECISION :: rv 
    INTEGER, INTENT(IN) :: n 
    DOUBLE PRECISION, PARAMETER :: minusone = -1.0 
    IF (n == 1) THEN 
     rv = 10 !exp(minusone) 
     RETURN 
    ELSE 
     rv = 1 - (n * integrate(n - 1)) 
     RETURN 
    END IF 
END FUNCTION integrate 

RECURSIVE FUNCTION factorial(n) RESULT(res) 
    INTEGER res, n 
    IF (n .EQ. 0) THEN 
     res = 1 
    ELSE 
     res = n * factorial(n - 1) 
    END IF 
END 

PROGRAM main 
    DOUBLE PRECISION :: rv1 
    PRINT *, factorial(5) 
    PRINT *, integrate(2) 

    !READ *, rv1 

END PROGRAM main 

इस कार्यक्रम के लिए उत्पादन होता है:

  NaN 
     1 

तो मैं प्रिंट बयान के आदेश (लाइन 30 & 31) बदलने के लिए, उत्पादन होगा:

  1 
-19.000000 

आउटपुट होना चाहिए (मूल प्रिंट स्टेटमेंट ऑर्डर के लिए):

120 
    -19 

मैंने विकिपीडिया Fortran 95 language features पृष्ठ से फैक्टोरियल फ़ंक्शन लिया। मैं फ़ोरट्रान में नया हूं, मुझे नहीं पता कि मेरे कोड में क्या गलत है। कृपया मुझे लोगों की मदद करो।

  • संकलक: gfortran 4.5.3 Cygwin
  • IDE के साथ: Netbeans 7.0.1
  • प्लेटफ़ॉर्म: Windows 7

अग्रिम धन्यवाद।

+0

बहुत अच्छा सवाल है, एक पुनरावर्ती कार्य सुविधा और विस्तार पर ध्यान देने के लिए तैयार हैं। धन्यवाद। –

उत्तर

8

आपके कार्य सही तरीके से लिखे गए हैं। समस्या मुख्य कार्यक्रम है, जहां आप स्पष्ट रूप से integrate और factorial कार्यों के प्रकार की घोषणा नहीं है में है, इसलिए आप अंतर्निहित टाइपिंग, जिसमें मामले factorialREAL माना जाता है और integrateINTEGER माना जाता है की है। किसी कारण से, आपके कंपाइलर ने आपको टाइप मिस्चैच के बारे में चेतावनी नहीं दी है। मेरा क्या किया:

PROGRAM main 
    IMPLICIT NONE 
    DOUBLE PRECISION, EXTERNAL :: integrate 
    INTEGER, EXTERNAL :: factorial 
    PRINT *, factorial(5) 
    PRINT *, integrate(2) 
END PROGRAM main 

सूचना IMPLICIT NONE लाइन:

$ gfortran recurs.f90 
recurs.f90:26.22: 

    PRINT *, integrate(2) 
         1 
Error: Return type mismatch of function 'integrate' at (1) (INTEGER(4)/REAL(8)) 
recurs.f90:27.22: 

    PRINT *, factorial(5) 
         1 
Error: Return type mismatch of function 'factorial' at (1) (REAL(4)/INTEGER(4)) 

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

उत्पादन अब है:

  120 
    -19.0000000000000  

अपेक्षा के अनुरूप।

एक तरफ ध्यान दें के रूप में, DOUBLE PRECISION प्रकार घोषणा उदा REALKIND पैरामीटर के साथ बजाय निर्दिष्ट का उपयोग करते हुए, के रूप में के रूप में लचीला नहीं है एक REAL(KIND=myRealKind)KIND का उपयोग कैसे करें: Fortran 90 kind parameter का उपयोग करने के तरीके के बारे में इस प्रश्न के उत्तर देखें।

+0

धन्यवाद @ आईआरओ-बॉट, जिसने बहुत अच्छा काम किया, धन्यवाद। –

+0

@ सजीतजनाप्रसाद आपका स्वागत है। ध्यान दें कि जब किसी का जवाब उपयोगी होता है, तो आप उत्तर के ऊपरी बाएं कोने में ऊपर तीर पर क्लिक करके भी ऊपर उठा सकते हैं। – milancurcic

+0

हाँ, मुझे पता है। मैंने ऊपर तीर पर क्लिक किया, लेकिन मैं ऊपर नहीं जा सकता, क्योंकि मेरे पास 15 प्रतिष्ठा नहीं है। माफ़ करना दोस्त। साइड नोट के लिए फिर से धन्यवाद। –

10

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

यदि आप जितना संभव हो उतने डिबगिंग विकल्पों का उपयोग करते हैं तो संकलक आपको गलतियों को ढूंढने में मदद करेगा। Gfortran के साथ, कोशिश करें: -O2 -fimplicit-none -Wall -Wline-truncation -Wcharacter-truncation -Wururprising -Waliasing -Wimplicit-interface -Wunused-parameter -fwhole-file -fcheck = all -std = f2008 -pedantic -fbacktrace

module factorial_procs 

    IMPLICIT NONE 

contains 

    RECURSIVE FUNCTION integrate(n) RESULT(rv) 
     DOUBLE PRECISION :: rv 
     INTEGER, INTENT(IN) :: n 

     IF (n == 1) THEN 
      rv = 10 
      RETURN 
     ELSE 
      rv = 1 - (n * integrate(n - 1)) 
      RETURN 
     END IF 
    END FUNCTION integrate 

    RECURSIVE FUNCTION factorial(n) RESULT(res) 
     INTEGER res, n 
     IF (n .EQ. 0) THEN 
      res = 1 
     ELSE 
      res = n * factorial(n - 1) 
     END IF 
    END 

end module factorial_procs 

PROGRAM main 

    use factorial_procs 

    implicit none 

    PRINT *, factorial(5) 
    PRINT *, integrate(2) 

END PROGRAM main 

आपको शायद पता चलेगा कि आप केवल नियमित पूर्णांक का उपयोग करके सीधे आगे गुणा करके बहुत छोटे पूर्णांक के फैक्टोरियल की गणना कर सकते हैं। एक ठीक,,

integer, parameter :: BigInt_K = selected_int_kind (18) 

आप को आधुनिक बनाने और डबल प्रेसिजन के बजाय selected_real_kind इस्तेमाल कर सकते हैं बस के रूप में एक बड़ा पूर्णांक प्रकार का प्रयोग है जैसे।

+2

"मॉड्यूल का उपयोग करें" टिप के लिए धन्यवाद, इससे मुझे एक और समस्या हल करने में मदद मिली। –

+0

मॉड्यूल आपके अधिकांश कार्यक्षमताओं को लिखने का सबसे अच्छा तरीका है। – Zeus

0
I would like to highlight some points while using RECURSIVE functions or non recursive function. 

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

PROGRAM main 
IMPLICIT NONE 
    INTERFACE 
    FUNCTION factorial(n) 
    INTEGER:: factorial 
    INTEGER, INTENT(IN):: n 
    END FUNCTION factorial 

    FUNCTION integrate(n) 
    DOUBLE PRECISION:: integrate 
    INTEGER, INTENT(IN):: n 
    END FUNCTION integrate 
END INTERFACE 

PRINT *, factorial(5) 
PRINT *, integrate(2) 

END PROGRAM main 

टिप्पणी यह ​​हमेशा के रूप में बेहतर तरह खंड का उपयोग कर तरह पैरामीटर और फिर परिभाषित करने के लिए द्वारा @milancurcic

समझाया अपनी समस्या को हल करने के लिए एक और बहुत ही सरल तरीका है: बस मुख्य कार्यक्रम में भाज्य और itegrate को परिभाषित निम्नानुसार है और आप

PROGRAM main 
IMPLICIT NONE 
    DOUBLE PRECISION :: integrate 
    INTEGER:: factorial 
    PRINT *, factorial(5) 
    PRINT *, integrate(2) 

END PROGRAM main