클로저에서 지수화하려면 어떻게해야합니까? 지금은 정수 지수화 만 필요하지만 문제는 분수에도 적용됩니다.
클로저에서 지수화하려면 어떻게해야합니까? 지금은 정수 지수화 만 필요하지만 문제는 분수에도 적용됩니다.
답변:
고전적인 재귀 (이것을보세요, 그것은 스택을 날려 버립니다)
(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)
Clojure에는 잘 작동하는 강력한 기능이 있습니다. 모든 Clojure 임의 정밀도 숫자 유형을 올바르게 처리하므로 Java interop을 사용하는 것보다 이것을 사용하는 것이 좋습니다. 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 네임 스페이스에 clojure.math.numeric-tower
액세스 할 수 있도록 하려면 먼저 Java 패키지 를 설치해야합니다 !
명령 줄에서 :
$ lein new my-example-project
$ cd lein new my-example-project
그런 다음 종속성 벡터를 편집 project.clj
하고 추가 [org.clojure/math.numeric-tower "0.0.4"]
합니다.
lein REPL 시작 (클로저 REPL 아님)
$ 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
Java Math.pow
또는 BigInteger.pow
메소드를 사용할 수 있습니다 .
(Math/pow base exponent)
(.pow (bigint base) exponent)
Math/pow
가 math-pow
이름이 무엇이든간에 얼마나 복잡한 지 모르겠습니다 . 원하는 작업을 수행하는 간단한 Java 메서드가 이미있는 경우 clojure에서 기능을 다시 만들 이유가 없습니다. Java interop은 본질적으로 해롭지 않습니다.
이 질문이 처음에 제기되었을 때 clojure.contrib.math / expt가이 를 수행하는 공식 라이브러리 기능이었습니다. 그 이후로 clojure.math.numeric-tower 로 이동했습니다.
user=> (.pow (BigInteger. "2") 10)
1024
user=> (.pow (BigInteger. "2") 100)
1267650600228229401496703205376
(.pow 2M 100)
(Math/pow Math/E x)
위해 트릭 Math/E
을 수행합니다 (선택한 기반으로 대체 ).
메서드가 아니라 함수가 정말로 필요한 경우 간단히 래핑 할 수 있습니다.
(defn pow [b e] (Math/pow b e))
그리고이 함수에서 당신은 그것을 int
또는 유사하게 캐스팅 할 수 있습니다 . 함수는 다른 함수에 매개 변수로 전달할 수 있기 때문에 메서드보다 종종 더 유용합니다 map
.
Java interop을 피해야하는 경우 고유 한 power 함수를 작성할 수 있습니다. 예를 들어 다음은 간단한 함수입니다.
(defn pow [n p] (let [result (apply * (take (abs p) (cycle [n])))]
(if (neg? p) (/ 1 result) result)))
정수 지수 (즉, 근 없음)에 대한 검정력을 계산합니다.
또한 많은 수를 처리 하는 경우 BigInteger
대신 을 사용할 수 있습니다 int
.
그리고 매우 큰 숫자를 처리하는 경우 숫자 목록으로 표현하고 결과를 계산하고 결과를 다른 스트림에 출력 할 때 자신의 산술 함수를 작성하여 스트리밍 할 수 있습니다.
사용 clojure.math.numeric-tower
이전에, 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))
꼬리 재귀를 사용하고 음의 지수를 지원하는 "sneaky"방법 구현 :
(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)))))))
reduce를 사용하는 간단한 한 줄 :
(defn pow [a b] (reduce * 1 (repeat b a)))
clojure.contrib.genric.math-functions는 어떻습니까?
clojure.contrib.generic.math-functions 라이브러리에는 pow 함수가 있습니다. 이것은 Math.pow의 매크로 일 뿐이며 Java 수학 함수를 호출하는 "clojureish"방식에 가깝습니다.