StackOverFlow, считая цифры

Я пытаюсь посчитать количество цифр в числе в 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, чтобы преобразовать это Число в вектор цифр и требования рассчитывает на него.

Спасибо,
Аджей Г.

9
задан user855 21 January 2010 в 18:41
поделиться

4 ответа

Там нет оптимизации хвостовой связи в 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)))
4
ответ дан 4 December 2019 в 11:41
поделиться

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))))
3
ответ дан 4 December 2019 в 11:41
поделиться

Согласно Эта страница , вы можете выполнить целочисленное разделение в Clojure, используя : :

(quot n 10)
3
ответ дан 4 December 2019 в 11:41
поделиться

Вот почему у вас возникла проблема:

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

Все версии по-своему интересны. Хороший вопрос!

8
ответ дан 4 December 2019 в 11:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: