আমি কীভাবে ক্লোজারে এক্সপেনশনেশন করতে পারি? আপাতত আমার কেবল পূর্ণসংখ্যার ক্ষয়ক্ষতি প্রয়োজন, তবে প্রশ্নটি ভগ্নাংশের ক্ষেত্রেও যায়।
আমি কীভাবে ক্লোজারে এক্সপেনশনেশন করতে পারি? আপাতত আমার কেবল পূর্ণসংখ্যার ক্ষয়ক্ষতি প্রয়োজন, তবে প্রশ্নটি ভগ্নাংশের ক্ষেত্রেও যায়।
উত্তর:
ক্লাসিক পুনরাবৃত্তি (এটি দেখুন, এটি স্ট্যাকটি উড়িয়ে দেয়)
(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.math.numeric - টাওয়ার ।
এটা তোলে বলা হচ্ছে expt
জন্য exponentiation বদলে 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
আপনি জাভা Math.pow
বা BigInteger.pow
পদ্ধতি ব্যবহার করতে পারেন :
(Math/pow base exponent)
(.pow (bigint base) exponent)
Math/pow
চেয়ে math-pow
নামটি যা কিছু জটিল বা কী জটিল তা আমি দেখতে পাই না । যদি ইতিমধ্যে যদি একটি সাধারণ জাভা পদ্ধতি থাকে যা আপনি যা করেন তা করেন তবে ক্লোজারে কার্যকারিতাটি পুনরায় তৈরি করার কোনও কারণ নেই। জাভা ইন্টারপ সহজাত ক্ষতিকারক নয়।
এই প্রশ্নটি যখন প্রাথমিকভাবে জিজ্ঞাসা করা হয়েছিল, Clojure.contrib.math / expt এটি করার জন্য অফিসিয়াল গ্রন্থাগারের কাজ ছিল। সেই থেকে এটি Clojure.math.numericmeric টাওয়ারে চলে গেছে
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
আমার মনে আসে।
আপনার যদি সত্যিই জাভা ইন্টারপ এড়ানো প্রয়োজন, আপনি নিজের পাওয়ার ফাংশনটি লিখতে পারেন। উদাহরণস্বরূপ, এটি একটি সাধারণ ফাংশন:
(defn pow [n p] (let [result (apply * (take (abs p) (cycle [n])))]
(if (neg? p) (/ 1 result) result)))
এটি পূর্ণসংখ্যার বেদী (যেমন কোনও শিকড় নয়) এর জন্য পাওয়ার গণনা করে।
এছাড়াও, যদি আপনি বড় সংখ্যক নিয়ে কাজ করে থাকেন তবে আপনি এর BigInteger
পরিবর্তে ব্যবহার করতে পারেন int
।
এবং যদি আপনি খুব সংখ্যক সংখ্যার সাথে ডিল করছেন , আপনি তাদের অঙ্কের তালিকা হিসাবে প্রকাশ করতে চাইতে পারেন এবং ফলাফলটি গণনা করার সাথে সাথে ফলাফলগুলিকে অন্য কোনও স্ট্রিমে আউটপুট দেওয়ার কারণে আপনার নিজের গাণিতিক ক্রিয়াগুলি তাদের উপরে প্রবাহিত করতে লিখতে পারেন।
আমি মনে করি এটি খুব কার্যকর হবে:
(defn expt [x pow] (apply * (repeat pow x)))
এস আই সি পি উপরে ' স্নেকি ' বাস্তবায়নের পূর্ণ পুনরাবৃত্তি দ্রুত সংস্করণ দ্বারা অনুপ্রাণিত হয়েছে ।
(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)))
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))
লেজ পুনরাবৃত্তি এবং নেতিবাচক ঘনিষ্ঠ সমর্থনকারী "স্নিগ্ধ" পদ্ধতির বাস্তবায়ন:
(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)))))))
হ্রাস ব্যবহার করে একটি সাধারণ ওয়ানলাইনার:
(defn pow [a b] (reduce * 1 (repeat b a)))
চেষ্টা
(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)))))
একটি লেজ পুনরুক্তিযোগ্য ও (লগ এন) সমাধানের জন্য, আপনি যদি এটি নিজে প্রয়োগ করতে চান (কেবলমাত্র ইতিবাচক পূর্ণসংখ্যার সমর্থন করে)। স্পষ্টতই, আরও ভাল সমাধান হ'ল লাইব্রেরির ফাংশনগুলি ব্যবহার করা যা অন্যরা উল্লেখ করেছে।
কিভাবে সম্পর্কে Clojure.contrib.genric.math- ফাংশন
Clojure.contrib.generic.math- ফাংশন লাইব্রেরিতে একটি পাওয়ার ফাংশন রয়েছে। এটি ম্যাথ.প্যাওয়ের কাছে কেবলমাত্র একটি ম্যাক্রো এবং জাভা গণিত ফাংশনটি কল করার আরও "ক্লোজারিশ" উপায়।