क्लोजर में घातांक कैसे करें?


106

मैं क्लोजर में एक्सप्रेशन कैसे कर सकता हूं? अभी के लिए मुझे केवल पूर्णांक घातांक की आवश्यकता है, लेकिन प्रश्न अंशों के लिए भी जाता है।


18
जैसे कि कोई व्यक्ति क्लोजर को नहीं जानता है, लेकिन इसे पसंद करने के लिए तैयार है (लिस्प्स, फंक्शनल प्रोग्रामिंग और बहुत सारे लाइब्रेरियों के प्रशंसक होने के नाते), मुझे यह देखकर निराशा हुई कि इस सरल प्रश्न के इतने उत्तर हैं - या यह बिल्कुल पूछा जाना था। मुझे लगता है कि घातांक बस बुनियादी कार्यों में से एक होगा जो बिना कुछ विशेष करने के लिए प्रदान किया जाता है। मुझे खुशी है कि यह पूछा गया था, हालांकि।
मंगल

1
अच्छी तरह से हाँ शायद इसका कुछ संस्करण कोर में होना चाहिए ... लेकिन मुझे लगता है कि कई उत्तर अभी भी एक अच्छा संकेत है। "कार्यान्वयन के लिए कई रास्ते" के कारण ऐसा प्रतीत होता है कि इनमें से बहुत सी चीजें प्रदान नहीं की गई हैं - उपयोगकर्ता को दक्षता के लिए उपयोग किए जाने वाले फ़ंक्शन का विवरण जानना चाहिए। उदाहरण के लिए (जैसा कि चुने गए उत्तर में बताया गया है) कुछ तरीके संभवतः स्टैक को उड़ा सकते हैं, दूसरों को ऐसा करने की संभावना कम है। शायद कुछ आलसी हैं, कुछ उत्सुक हैं ... सभी विवरण जिन्हें क्लीजोर में कुछ ध्यान देने की आवश्यकता है, यही कारण है कि मुझे लगता है कि दर्शन के कारण सबसे गैर-तुच्छ काम उपलब्ध नहीं हैं
jm0

3
मुझे लगता है कि कोर में सिर्फ एक एक्सपेक्ट फंक्शन की वजह नहीं है क्योंकि दक्षता कारणों से क्लोजर का न्यूमेरिक टॉवर बुरी तरह से टूट गया है। इसलिए हर तरह की अलग-अलग चीजें होती हैं जिनका आप मतलब निकाल सकते हैं। क्या होना चाहिए (एक्सप २ (एक्सप २ २००))? एक त्रुटि या एक विशाल पूर्णांक जो गणना करने के लिए एक आयु लेता है? यदि आप केवल सामान्य फ्लोटिंग पॉइंट एक्सप चाहते हैं, तो जावा एक में बनाया गया है। यदि आप एक ऐसी भाषा चाहते हैं, जहाँ संख्याएँ वास्तविक की तरह कार्य करने के लिए अपनी पूरी कोशिश करें, और कॉज़ के बजाय लागत का उपयोग करें।
जॉन लॉरेंस एस्पेन

जवाबों:


141

क्लासिक पुनरावर्तन (इसे देखें, यह स्टैक को उड़ा देता है)

(defn exp [x n]
     (if (zero? n) 1
         (* x (exp x (dec n)))))

पूंछ की पुनरावृत्ति

(defn exp [x n]
  (loop [acc 1 n n]
    (if (zero? n) acc
        (recur (* x acc) (dec n)))))

कार्यात्मक

(defn exp [x n]
  (reduce * (repeat n x)))

डरपोक (स्टैक भी उड़ाता है, लेकिन इतनी आसानी से नहीं)

(defn exp-s [x n]
  (let [square (fn[x] (* x x))]
    (cond (zero? n) 1
          (even? n) (square (exp-s x (/ n 2)))
          :else (* x (exp-s x (dec n))))))

पुस्तकालय

(require 'clojure.contrib.math)

11
मनोरंजक जवाब!
मैट फेनविक

नीचे डरपोक समाधान के लिए पूरी तरह से पुनरावृत्ति संस्करण देख stackoverflow.com/a/22977674/231589
कार्ल Rosaen

5
Clojure.contrib.math अब पदावनत हो गई है, देखें Math.Numeric-Tower
alvaro g

दूसरा सुझाव (पूंछ पुनरावर्ती) में एन <0. के लिए पूर्णांक अतिप्रवाह है
22o पर पॉइंटो सेन्शी

1
शानदार जवाब। यहाँ एक मैक्रो के साथ यह कैसे करना है: (डिफैक्रो एक्सप [xn] `(* ~ @ (n (रिपीट x))))
डैनियल स्ज़ुम्विक्ज़

78

क्लोजर में एक शक्ति फ़ंक्शन होता है जो अच्छी तरह से काम करता है: मैं जावा इंटरॉप के माध्यम से जाने के बजाय इसका उपयोग करने की सलाह दूंगा क्योंकि यह सभी क्लोजर मनमाना-सटीक संख्या प्रकारों को सही ढंग से संभालता है। यह नामस्थान clojure.math.numeric-Tower में है

यह कहा जाता है exptके लिए घातांक के बजाय powerया powजो शायद यही कारण है यह थोड़ा मुश्किल लगता करने के लिए है ... वैसे भी यहाँ एक छोटा सा उदाहरण है (ध्यान दें कि useकाम करता है लेकिन बेहतर इस्तेमाल require):

(require '[clojure.math.numeric-tower :as math :refer [expt]])  ; as of Clojure 1.3
;; (use 'clojure.contrib.math)     ; before Clojure 1.3
(expt 2 200)
=> 1606938044258990275541962092341162602522202993782792835301376

पैकेज स्थापना के बारे में अनुस्मारक

org.clojure.math.numeric-towerक्लोजर नेमस्पेस को clojure.math.numeric-towerसुलभ बनाने के लिए आपको सबसे पहले जावा पैकेज स्थापित करना होगा !

कमांड लाइन पर:

$ lein new my-example-project
$ cd lein new my-example-project

फिर निर्भरता वेक्टर में संपादित करें project.cljऔर जोड़ें [org.clojure/math.numeric-tower "0.0.4"]

लेइन आरईपीएल शुरू करें (क्लोजर आरईपीएल नहीं)

$ lein repl

अभी:

(require '[clojure.math.numeric-tower :as math])
(math/expt 4 2)
;=> 16

या

(require '[clojure.math.numeric-tower :as math :refer [expt]])
(expt 4 2)
;=> 16

1
संभवतया अज्ञात है क्योंकि यह मानक क्लोजर का हिस्सा प्रतीत नहीं होता है। जब मैं इसे इस तरह से करने की कोशिश कर रहा हूं, तो गणित को खोजने में सक्षम नहीं होने के बारे में 1.3.0 त्रुटियां हैं।
ब्रायन नोब्लुक

9
मुझे लगता है कि अब यह 1.3 के रूप में "clojure.math.numeric- टॉवर" में है (चूंकि clojure.contrib अलग-अलग पुस्तकालयों में टूट गया है)
mikera

जोड़ा "पैकेज स्थापना के बारे में अनुस्मारक" उपयोगकर्ता हताशा के लिए।
डेविड टोनहोफर

60

आप जावा Math.powया BigInteger.powविधियों का उपयोग कर सकते हैं :

(Math/pow base exponent)

(.pow (bigint base) exponent)

+1, हालांकि मुझे पता है कि आप जावा लिबास के साथ इंटरोप कर सकते हैं; हालाँकि, 1) Math.pow डबल्स के साथ काम करता है, मुझे Integers की ज़रूरत है, क्या आप एक उदाहरण दे सकते हैं? 2) क्या आपको वास्तव में sth के लिए इंटरॉप का उपयोग करना है। शक्तियों के रूप में सरल?
पीटर

क्लोजर को जावा लाइब्रेरी के चारों ओर बनाया गया है, जो टूटा नहीं है उसे ठीक करने का प्रयास नहीं करता है और मैथ / पॉव ठीक काम करता है। आपको डबल्स या पूर्णांक की देखभाल करने की आवश्यकता क्यों है? आप भी इस का उपयोग कर सकते richhickey.github.com/clojure-contrib/...
DaVinci

1
@ पेटर: 1) जब तक आपकी शक्तियां इतनी बड़ी नहीं होती हैं कि उन्हें अब डबल्स द्वारा सटीक रूप से प्रस्तुत नहीं किया जा सकता है, वास्तव में रिजल्ट को इंट में डालने के साथ कोई समस्या नहीं है। 2) मैं नहीं देखता कि लेखन कैसे Math/powअधिक जटिल है math-powया जो भी नाम होगा अगर वहाँ एक क्लोजर बराबर था। यदि पहले से ही एक सरल जावा विधि है जो आप चाहते हैं, तो क्लोजर में कार्यक्षमता को फिर से बनाने का कोई कारण नहीं है। जावा इंटरॉप स्वाभाविक रूप से हानिकारक नहीं है।
sepp2k

3
@ डीए विजा: अजीब टिप्पणी, यह स्वयं की एक भाषा है, और इसमें बहुत सारे कार्य हैं जो जावा में हैं (जैसे स्ट्रेववर्स)
पीटर 12

4
मुझे लगता है कि अगर आप सटीक बिगिन्टेगर शक्तियां चाहते हैं, तो आप क्लोज़र की क्लोजर.कॉन्स्ट्रिबामथ / एक्सपट्ट का उपयोग करना बेहतर है। शायद हुड के तहत एक ही है, लेकिन जावा इंटरॉप के माध्यम से जाने की तुलना में बहुत अच्छा है .....
mikera

13

जब यह प्रश्न मूल रूप से पूछा गया था, तो clojure.contrib.math / expt ऐसा करने के लिए आधिकारिक पुस्तकालय कार्य था। तब से, यह clojure.math.numeric-Tower में चला गया है


इस उत्तर के लिए +1 चूंकि यह सभी क्लोजर को सटीक (यानी बिगडेसिमल / बिगइंटर) अंकगणित को सही ढंग से संभालता है।
मिकेरा


8
user=> (.pow (BigInteger. "2") 10)
1024
user=> (.pow (BigInteger. "2") 100)
1267650600228229401496703205376

6
इसके अलावा आप इसके लिए शाब्दिक संकेतन का उपयोग कर सकते हैं:(.pow 2M 100)
noisesmith

1
उनके प्रकार अलग हैं। user => (टाइप 2M) java.math.BigDecimal यूजर => (टाइप (BigInteger। "2")) java.math.BigInteger
KIM Taegyoon

Imo सबसे अच्छा समाधान, showr, मौजूदा पुस्तकालयों का उपयोग कर, और bigint से निपटने सहित। +1
डैनियल ग्रूसज़िक

मेरे (Math/pow Math/E x)लिए ट्रिक ( Math/Eआपकी पसंद के आधार के साथ प्रतिस्थापित ) करता है।
ज़ाज़

6

यदि आपको वास्तव में एक फ़ंक्शन की आवश्यकता है और एक विधि की नहीं, तो आप इसे बस लपेट सकते हैं:

 (defn pow [b e] (Math/pow b e))

और इस फंक्शन में आप इसे intया इसी तरह का कास्ट कर सकते हैं । फ़ंक्शंस अक्सर अधिक उपयोगी होते हैं जो विधियाँ क्योंकि आप उन्हें अन्य कार्यों के लिए मापदंडों के रूप में पारित कर सकते हैं - इस मामले mapमें मेरे दिमाग में आता है।

यदि आपको वास्तव में जावा इंटरॉप से ​​बचने की आवश्यकता है, तो आप अपना स्वयं का पावर फ़ंक्शन लिख सकते हैं। उदाहरण के लिए, यह एक सरल कार्य है:

 (defn pow [n p] (let [result (apply * (take (abs p) (cycle [n])))]
   (if (neg? p) (/ 1 result) result)))

यह पूर्णांक घातांक (यानी कोई जड़ नहीं) के लिए शक्ति की गणना करता है।

इसके अलावा, यदि आप बड़ी संख्या के साथ काम कर रहे हैं, तो आप इसके BigIntegerबजाय उपयोग करना चाह सकते हैं int

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


4

मुझे लगता है कि यह भी काम करेगा:

(defn expt [x pow] (apply * (repeat pow x)))

लेकिन 2 ^ 63 पर अधिकतम करने के लिए लगता है ... 2 ^ 200 में सक्षम नहीं
TJ Trapp

4

SICP ने उपरोक्त 'डरपोक' कार्यान्वयन के पूर्ण पुनरावृत्त तेज संस्करण को प्रेरित किया।

(defn fast-expt-iter [b n]
  (let [inner (fn [a b n]
                (cond
                  (= n 0) a
                  (even? n) (recur a (* b b) (/ n 2))
                  :else (recur (* a b) b (- n 1))))
        ]
    (inner 1 b n)))


2

पूंछ पुनरावृत्ति और नकारात्मक प्रतिपादक का समर्थन करने के साथ "डरपोक" विधि का कार्यान्वयन:

(defn exp
  "exponent of x^n (int n only), with tail recursion and O(logn)"
   [x n]
   (if (< n 0)
     (/ 1 (exp x (- n)))
     (loop [acc 1
            base x
            pow n]
       (if (= pow 0)
         acc                           
         (if (even? pow)
           (recur acc (* base base) (/ pow 2))
           (recur  (* acc base) base (dec pow)))))))


1

प्रयत्न

(defn pow [x n]
  (loop [x x n n r 1]
    (cond
      (= n 0) r
      (even? n) (recur (* x x) (/ n 2) r)
      :else (recur x (dec n) (* r x)))))

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


0

कैसे के बारे में clojure.contrib.genric.math-functions

Clojure.contrib.generic.math-functions लाइब्रेरी में एक पॉव फंक्शन है। यह Math.pow के लिए एक मैक्रो है और जावा गणित फ़ंक्शन को कॉल करने के "क्लोजुरिश" तरीके से अधिक है।

http://clojure.github.com/clojure-contrib/generic.math-functions-api.html#clojure.contrib.generic.math-functions/pow


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