Comment puis-je faire de l'exponentiation en clojure? Pour l'instant, je n'ai besoin que d'exponentiation entière, mais la question vaut aussi pour les fractions.
Comment puis-je faire de l'exponentiation en clojure? Pour l'instant, je n'ai besoin que d'exponentiation entière, mais la question vaut aussi pour les fractions.
Réponses:
récursion classique (regardez ça, ça souffle pile)
(defn exp [x n]
     (if (zero? n) 1
         (* x (exp x (dec n)))))récursion de queue
(defn exp [x n]
  (loop [acc 1 n n]
    (if (zero? n) acc
        (recur (* x acc) (dec n)))))fonctionnel
(defn exp [x n]
  (reduce * (repeat n x)))sournois (souffle également la pile, mais pas si facilement)
(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))))))bibliothèque
(require 'clojure.contrib.math)Clojure a une fonction d'alimentation qui fonctionne bien: je recommanderais de l'utiliser plutôt que de passer par l'interopérabilité Java car il gère correctement tous les types de nombres à précision arbitraire Clojure. Il se trouve dans l'espace de noms clojure.math.numeric-tower .
C'est appelé exptà l' exponentiation plutôt que powerou powce qui explique peut-être pourquoi c'est un peu difficile à trouver ... en tout cas voici un petit exemple (note qui usefonctionne mais mieux utiliser 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)
=> 1606938044258990275541962092341162602522202993782792835301376Vous devez d'abord installer le package Java org.clojure.math.numeric-towerpour rendre l'espace de noms Clojure clojure.math.numeric-toweraccessible!
Sur la ligne de commande:
$ lein new my-example-project
$ cd lein new my-example-projectPuis éditez project.cljet ajoutez [org.clojure/math.numeric-tower "0.0.4"]au vecteur de dépendances.
Démarrer un lein REPL (pas un clojure REPL)
$ lein replMaintenant:
(require '[clojure.math.numeric-tower :as math])
(math/expt 4 2)
;=> 16ou
(require '[clojure.math.numeric-tower :as math :refer [expt]])
(expt 4 2)
;=> 16Vous pouvez utiliser les méthodes Math.powou Java BigInteger.pow:
(Math/pow base exponent)
(.pow (bigint base) exponent)Math/powest plus compliquée math-powou quel que soit le nom s'il y avait un équivalent clojure. S'il existe déjà une méthode java simple qui fait ce que vous voulez, il n'y a aucune raison de recréer la fonctionnalité dans clojure. L'interopérabilité Java n'est pas intrinsèquement nuisible.
                    Lorsque cette question a été posée à l'origine, clojure.contrib.math / expt était la fonction officielle de la bibliothèque pour ce faire. Depuis, il est passé à clojure.math.numeric-tower
user=> (.pow (BigInteger. "2") 10)
1024
user=> (.pow (BigInteger. "2") 100)
1267650600228229401496703205376(.pow 2M 100)
                    (Math/pow Math/E x)fait l'affaire (en remplaçant Math/Epar la base de votre choix).
                    Si vous avez vraiment besoin d'une fonction et non d'une méthode, vous pouvez simplement l'envelopper:
 (defn pow [b e] (Math/pow b e))Et dans cette fonction, vous pouvez le lancer intou similaire. Les fonctions sont souvent plus utiles que les méthodes car vous pouvez les passer en tant que paramètres à d'autres fonctions - dans ce cas, cela mapme vient à l'esprit.
Si vous avez vraiment besoin d'éviter l'interopérabilité Java, vous pouvez écrire votre propre fonction d'alimentation. Par exemple, c'est une fonction simple:
 (defn pow [n p] (let [result (apply * (take (abs p) (cycle [n])))]
   (if (neg? p) (/ 1 result) result)))Cela calcule la puissance pour l'exposant entier (c'est-à-dire pas de racines).
De plus, si vous avez affaire à de grands nombres, vous pouvez utiliser à la BigIntegerplace de int.
Et si vous avez affaire à de très grands nombres, vous voudrez peut-être les exprimer sous forme de listes de chiffres et écrire vos propres fonctions arithmétiques pour les parcourir au fur et à mesure qu'ils calculent le résultat et envoient le résultat vers un autre flux.
SICP a inspiré la version rapide itérative complète de l'implémentation «sournoise» ci-dessus.
(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)))Utilisez clojure.math.numeric-tower, autrefois clojure.contrib.math.
(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))Implémentation de la méthode "sournoise" avec récursion de queue et supportant l'exposant négatif:
(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)))))))Un simple one-liner utilisant réduire:
(defn pow [a b] (reduce * 1 (repeat b a)))Essayer
(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)))))pour une solution O (log n) récursive à la fin, si vous souhaitez l'implémenter vous-même (ne prend en charge que les entiers positifs). De toute évidence, la meilleure solution est d'utiliser les fonctions de bibliothèque que d'autres ont indiquées.
Que diriez-vous de clojure.contrib.genric.math-functions
Il existe une fonction pow dans la bibliothèque clojure.contrib.generic.math-functions. C'est juste une macro de Math.pow et c'est plus une façon "clojureish" d'appeler la fonction mathématique Java.