Jak zrobić wykładnik w clojure?

Jak zrobić wykładnik w clojure? Na razie potrzebuję tylko wykładnika liczby całkowitej, ale pytanie dotyczy też ułamków.

Author: ThinkingStiff, 2011-02-20

13 answers

Rekurencja Klasyczna (patrz na to, wieje stos)

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

Rekurencja ogona

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

Funkcjonalne

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

Sneaky (również wieje stack, ale nie tak łatwo)

(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))))))

Biblioteka

(require 'clojure.contrib.math)
 122
Author: John Lawrence Aspden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-20 17:42:27

Clojure ma funkcję mocy, która działa dobrze: zalecałbym jej używanie, a nie przechodzenie przez Java interop, ponieważ obsługuje wszystkie typy liczb arbitralnie precyzyjnych Clojure poprawnie.

Nazywa się exptdla wykładnik zamiast power lub pow, co może wyjaśniać, dlaczego jest trochę trudne do znalezienia..... w każdym razie oto mały przykład:

(use 'clojure.contrib.math)

(expt 2 200)
=> 1606938044258990275541962092341162602522202993782792835301376

Od Clojure 1.3 funkcja Ta i inne powiązane funkcje matematyczne zostały przeniesione, więc musisz zrobić:

(use 'clojure.math.numeric-tower)
 72
Author: mikera,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-13 18:25:57

Możesz użyć metod Javy Math.pow lub BigInteger.pow:

(Math/pow base exponent)

(.pow (bigint base) exponent)
 50
Author: sepp2k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-20 13:02:48

Kiedy to pytanie zostało pierwotnie zadane, http://clojure.github.com/clojure-contrib/math-api.html#clojure.contrib.math/expt to miejsce, w którym funkcjonowała oficjalna biblioteka. Od tego czasu przeniósł się do https://github.com/clojure/math.numeric-tower/blob/master/src/main/clojure/clojure/math/numeric_tower.clj#L80

 11
Author: amalloy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-26 23:53:04
user=> (.pow (BigInteger. "2") 10)
1024
user=> (.pow (BigInteger. "2") 100)
1267650600228229401496703205376
 6
Author: KIM Taegyoon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-27 13:54:21

Jeśli naprawdę potrzebujesz funkcji, a nie metody, możesz ją po prostu owinąć:

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

I w tej funkcji można go wrzucić do {[2] } lub podobnego. Funkcje są często bardziej użyteczne niż metody, ponieważ można je przekazać jako parametry innym funkcjom-w tym przypadku przychodzi mi do głowy map.

Jeśli naprawdę chcesz uniknąć Java interop, możesz napisać własną funkcję power. Na przykład jest to prosta funkcja:

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

Który oblicza moc dla wykładnika całkowitego (tj. bez korzeni).

Ponadto, jeśli masz do czynienia z dużymi liczbami , możesz użyć BigInteger zamiast int.

A jeśli masz do czynienia z bardzo dużymi liczbami, możesz wyrazić je jako listy cyfr i napisać własne funkcje arytmetyczne, aby przesyłać je strumieniowo, gdy obliczają wynik i wysyłają wynik do innego strumienia.

 5
Author: Goran Jovic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-20 14:00:46

Myślę, że to też by zadziałało:

(defn expt [x pow] (apply * (repeat pow x)))
 4
Author: TJ Trapp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-12 07:56:41

SICP inspired Pełna iteracyjna szybka wersja' podstępnej ' implementacji powyżej.

(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
Author: Karl Rosaen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-10 02:41:58

Użycie clojure.math.numeric-tower, dawniej clojure.contrib.math.


Dokumentacja API


(ns user
  (:require [clojure.math.numeric-tower :as m]))

(defn- sqr
  "Uses the numeric tower expt to square a number"
  [x]
  (m/expt x 2))
 2
Author: micrub,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-30 18:10:26

Try

(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)))))

Dla rekurencyjnego rozwiązania o(log n), jeśli chcesz zaimplementować je samodzielnie (obsługuje tylko dodatnie liczby całkowite). Oczywiście lepszym rozwiązaniem jest użycie funkcji bibliotecznych, które wskazywali inni.

 1
Author: Retief,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-29 22:21:44

Implementacja metody "sneaky" z rekurencją ogonową i wsparciem wykładnika ujemnego:

(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
Author: Tolstoyevsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-06 13:53:00

A może clojure?contrib.genric.matematyka-funkcje

Istnieje funkcja pow w clojure.contrib.ogólne.biblioteka funkcji matematycznych. To tylko makro do matematyki.pow i jest bardziej "clojureish" sposobem wywoływania funkcji matematycznej Javy.

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

 0
Author: fido,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-20 21:13:26

A simple one-liner using reduce

(defn pow [a b] (reduce * 1 (repeat b a)))
 0
Author: Alan R. Soares,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-11 11:41:18