/ / हास्केल में डिवीजन, फिर भी नहीं मिलता है - हैस्केल, प्रकार, पूर्णांक, इंट, डिवीजन

हास्केल में डिवीजन, अभी भी इसे प्राप्त नहीं है - हैकेल, प्रकार, पूर्णांक, int, विभाजन

मैं अभी भी हास्केल में विभाजन को नहीं समझता हूं। मेरा पहला इरादा इस तरह एक कवक को परिभाषित करना था:

piApprox :: (Integral a, Fractional b) => a -> b
piApprox n = 4 * sum [ (-1)^k / (2*k + 1) | k <- [0..n] ]

यह "t काम नहीं करता है। फिर, हस्ताक्षर का उपयोग कर:

piApprox :: (Fractional a) => Int -> a

लेकिन यह फिर से उठता है "त्रुटि नहीं घटा सका"।

यदि मैं यह पता लगाने के लिए दुभाषिया में इस कोड को चलाता हूं कि क्या हस्ताक्षर सबसे अच्छा है, तो परिणाम है:

Prelude> let piApprox n = 4 * sum [ (-1)^k / (2*k + 1) | k <- [0..n] ]
Prelude> :t piApprox
piApprox :: (Fractional a, Integral a) => a -> a

जो "प्रकार चर` a0 "अस्पष्ट" त्रुटि "उठाता है।

अभी, इस गणना को करने का एकमात्र तरीका जो मैं सोच सकता था कि इसमें शामिल है Ratio पैकेज और फिर परिवर्तित करना double का उपयोग करके fromRational.

import Data.Ratio
piApprox n = (fromRational) $ 4 * sum [ (-1)^k % (2*k + 1) | k <- [0..n] ]

यह काम करता है, लेकिन मुझे लगता है कि सबसे अच्छा तरीका नहीं है।

मैंने यह भी सोचा था कि हस्ताक्षर, मध्यवर्ती संचालन में भी इनपुट और आउटपुट प्रकार सही थे (-1)^k / (2*k + 1) - जहां विभाजन रखा गया है - समस्या हो सकती है, इसलिए मैंने भी परिभाषित किया है:

piApprox" :: (Fractional a) => Int -> a
piApprox" n = 4 * sum [ (fromIntegral) $ (-1)^k / (2*k + 1) | k <- [0..n] ]

भाग्य से नहीं। मुझे यहां क्या समझ नहीं आ रहा है?

उत्तर:

जवाब के लिए 5 № 1

यह काम करना चाहिए:

piApprox n = 4 * sum [ fromIntegral ((-1)^k) / fromIntegral (2*k + 1) | k <- [0..n] ]

The fromIntegral समारोह का एक प्रकार हस्ताक्षर है:

(Integral a, Num b) => a -> b

इसलिए यह मूल रूप से आपके इंटीग्रल टाइप को एनयूएम टाइप में परिवर्तित करता है।

के जैसा (/) है:

Fractional a => a -> a -> a, इसलिए आपको इसके लिए आंशिक डेटा की आपूर्ति करनी होगी।

The fromIntegral फ़ंक्शन वास्तव में इसे एक में परिवर्तित करके इसे प्राप्त करेगा Num प्रकार जिसमें शामिल हैं Fractional प्रकार के।


जवाब के लिए 2 № 2

आपकी समस्या यह है कि आप असंगत संख्या प्रकारों को मिला रहे हैं। आपने कहा कि n कुछ है Integral (विशेष रूप से, इस मामले में पूर्णांक)। k <- [0..n] इसका मतलब है कि के समान है Integral प्रकार। तब आप उपयोग करते हैं / विभाजन, जिसका हिस्सा है Fractional कक्षा। जिसका मतलब है कि आपका परिणाम दोनों होना चाहिए Integral तथा Fractional, और मुझे नहीं लगता कि इस तरह का अस्तित्व है।

इसका उपयोग करने से पहले समाधान को अपने परिणाम प्रकार में बदलना होगा fromIntegral k.


जवाब के लिए 0 № 3

मैं इस हस्ताक्षर के लिए अधिवक्ता हूं:

piApprox :: (Fractional r) => Int -> r

कारण, "सटीक" पैरामीटरdoesn "t का कोई विशेष" मूल्य "अर्थ है, यह कार्य को चलाने के लिए कितने कदमों का एक काउंटर है" विचलन सही मूल्य के लिए π आप मूल्यांकन गहराई के बजाय अनुमति देना चाहते हैं, लेकिन यह अधिक जटिल है।

अगला, वह बिंदु जहां आपका सही कार्यान्वयन क्लैश होता है (-1)^k (इसकी जरूरत है Integral क्योंकि घातांक द्वारा कार्यान्वित किया जाता हैपुनरावर्ती गुणन)। हां, यह गणित और विज्ञान में एक वैकल्पिक संकेत को निरूपित करने का सामान्य तरीका है, लेकिन अगर आप इसके बारे में सोचते हैं तो यह बहुत बुरा तरीका है। आप वास्तव में यहां शक्तियों में रुचि नहीं रखते हैं, बस साइन-अल्टरनेशन में, और यह बहुत स्वाभाविक रूप से हासिल किया गया है cycle [1, -1].

गुणा के लिए यह अलग है, कि जरूरत नहीं है Integral लेकिन सभी दलीलों की आवश्यकता है वही प्रकार। इसे प्राप्त करने का प्राकृतिक तरीका है, एक का उपयोग करें Fractional चर एक अभिन्न एक से परिवर्तित करने के बजाय, तुरंत दूर! इसलिए इसके बजाय [0..n], आप उपयोग कर सकते हैं [0 .. fromIntegral n]। एक के बदले सिर्फ एक रूपांतरण प्रत्येक चरण पर.

वास्तव में, हालांकि, यह सूचकांकों को बाध्य नहीं करना बेहतर है! चूंकि यह हास्केल है, आप सूची को अनंत के रूप में परिभाषित कर सकते हैं (जैसे क्या cycle भी करता है)। बेशक आप एक अनंत सूची को "जोड़" सकते हैं, लेकिन ऐसा करने से पहले आप इसे ठीक से ट्रिम कर सकते हैं:

piApprox :: (Fractional r) => Int -> r
piApprox n = 4 * sum (take n [ σ / (2*k + 1) | (σ,k) <- zip (cycle [-1,1]) [0..] ])

या, शायद अच्छे से लिखा गया है ParallelListComprehensions विस्तार:

piApprox n = (4 *) . sum $
take n [ σ / (2*k + 1) | σ <- cycle [1, -1]
| k <- [0..]
]

यह आपके कार्यान्वयन से एक कदम कम है क्योंकि take n [0..] के बराबर है [0..n-1]। मुझे लगता है कि यह बहुत मायने नहीं रखता है, अन्यथा यह ठीक करने के लिए तुच्छ है।


अंत में: मुझे लगता है कि आप जानते हैं कि यह सूत्र अभिसरण गति के मामले में बहुत बुरा है!