Я пытаюсь посчитать количество цифр в числе в Clojure следующим образом: Я получаю StackOverflowError даже для 2 чисел цифры
(defn num-digits [n]
(if (= 0 n)
0
(inc (num-digits (/ n 10)))))
(println (num-digits 93))
Но если я заменяю / незарегистрированным - делятся тогда, это работает по крайней мере на 93. Но ни один из методов не работает на:
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
Во-первых, я хотел бы знать, как выполнить подразделение C-стиль в Clojure. Каждый раз, когда я делаю (/x y), я получаю Отношение и не Целое число. Что путь состоит в том, чтобы сделать это?
Во-вторых, есть ли способ, которым API, чтобы преобразовать это Число в вектор цифр и требования рассчитывает на него.
Спасибо,
Аджей Г.
Там нет оптимизации хвостовой связи в Cljure. Вы должны использовать специальную форму RECUR
.
E.g.:
(defn num-digits [n]
(loop [n n
cnt 0]
(if (= 0 n)
cnt
(recur (quot n 10) (inc cnt)))))
Но в ответ на ваш второй вопрос: да, и так:
(defn num-digits [n] (count (str n)))
Clojure пытается «сделать правильно» с числовыми операциями и никогда не теряют точность . Поэтому, когда вы используете устройство 17/10, результат - это фракция 17/10 (семнадцать десятых), а не 1. По умолчанию информация не будет потеряна в любой из численных операций. В таких случаях, как это вы можете явно выбрасывать дополнительную точность с (QUOTE X 10)
или вы можете изложить результат в INT (INT (/ 17 10))
для второго Вопрос Вот немного взлома:
(count (str 257))
Хороший способ сохранить от выдувания стека с рекурсией в Clojure - использовать другие функции более высокого порядка вместо рекурсии.
(count (take-while pos? (iterate #(quot % 10) 257))))
Согласно Эта страница , вы можете выполнить целочисленное разделение в Clojure, используя :
:
(quot n 10)
Вот почему у вас возникла проблема:
user> (take 10 (iterate #(/ % 10) 10923))
(10923 10923/10 10923/100 10923/1000 10923/10000 10923/100000 10923/1000000 10923/10000000 10923/100000000 10923/1000000000)
Это исправление:
user> (take 10 (iterate #(quot % 10) 10923))
(10923 1092 109 10 1 0 0 0 0 0)
Это выражение, которое вы ищете:
user> (count (take-while #(not (zero? %)) (iterate #(quot % 10) 10923)))
5
Это обман:
user> (count (str 10923))
5
Это функция, которую вы пытались написать (но будьте осторожны, она приведет к переполнению стека для больших чисел):
user> (defn num-digits [n]
(if (= 0 n)
0
(inc (num-digits (quot n 10)))))
#'user/num-digits
user> (num-digits 10923)
5
Однако это решает проблему:
user> (num-digits 93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000)
158
Эта версия этого функция не сдувает стек:
user> (defn num-digits-tail-recursion
([n count]
(if (= 0 n)
count
(recur (quot n 10) (inc count))))
([n] (num-digits-tail-recursion n 0)))
#'user/num-digits-tail-recursion
user> (num-digits-tail-recursion 10923)
5
Все версии по-своему интересны. Хороший вопрос!