LINUX.ORG.RU

Проблема с алгоритмом возведения в степень

 


0

1
(require 'debug)
(setq debug-on-quit t)
(setq x 2)
(setq n 3)
(setq r 1)
(while (< 0 n)
  (setq n (- n 1))
  (setq r (* r x)))   ;; такая версия нравится


(defun power (x n)
  (if (= 0 n)
      1
    (if (= 1 n)
	x
      (if (< 1 n)
	(setq r (* r (power x (- n 1))))))))
(trace-function 'power) ;; Lisp nesting exceeds ‘max-lisp-eval-depth’ не понятно где я накосячил аж Emacs виснет.
(power 2 3)

;;Этот алгоритм, просто супер, но результат, зараза, 7.9999999998
(defun pow (x n)
  (exp (* n (log x))))
(pow 2 3)

такие вот мысли. Нужно поменять expt x y в коде из-за её

If both arguments are integers and y is positive, the result is an integer; in this case, overflow causes truncation, so watch out. If x is a finite negative number and y is a finite non-integer, expt returns a NaN.



Последнее исправление: saufesma (всего исправлений: 1)
Ответ на: комментарий от saufesma
(print (expt 2 5))
>>> 32

upd. не заметил, что её и нужно заменить)

AKonia ★★
()
Последнее исправление: AKonia (всего исправлений: 1)
Ответ на: комментарий от AlexKiriukha

Я не фанат лиспянки, но - фуфуфу писать рекурсивные факториалы и возведение в степень вне университетского пруда для перваков.

AKonia ★★
()
Ответ на: комментарий от AlexKiriukha

Тут вот госпадин Дибвиг поделился кодом

(defun power (x n)
"Power raises x to the nth power. Ν must be an integer >= 0.
This executes in log n time, because of the check for even n.
(cond ((= n 0) 1)
((evenp n) (expt (power x (/ n 2 )) 2))
(t (* x (power x (- n 1))))))

хотелось бы увидеть (trace (power 2 3))

но не получается, подскажешь как?

saufesma
() автор топика
Ответ на: комментарий от AKonia

(defun pow(x n) (if(< n 0) 1 (if(= n 1) x (* x (pow x (- n 1)))) ) )

Может подскажешь почему

(trace-function ’pow)

выдаёт такое

Lisp nesting exceeds ‘max-lisp-eval-depth’

но код работает (pow 2 3) => 8

saufesma
() автор топика
Ответ на: комментарий от saufesma

есть ограничение на глубину вложенности(рекурсии), можно изменить ограничение так

(setq max-lisp-eval-depth 1000)

Но я бы рекомендовал переписать по старинке пошаговым умножением или оптимизированным(при чётном n возводим временный результат) в квадрат, а n делим на 2, т.к. так можно будет отвязаться от размера стека

AKonia ★★
()
Ответ на: комментарий от AKonia

(setq max-lisp-eval-depth 1000)

На этом я уже горел, у меня стек потек, пришлось всё переписывать в итеративном стиле.

Но я бы рекомендовал переписать по старинке пошаговым умножением или оптимизированным

У меня степени в основном float, и отрицательные числа возводятся в степень. Т.е. там где expt x y

If x is a finite negative number and y is a finite non-integer, expt returns a NaN.

И вот это надо как то обрулить.

saufesma
() автор топика
Ответ на: комментарий от saufesma
(defun pow (x n)
    (setq res 1)
    (loop for i from 1 to n
         do(setq res (* res x)
           )
    )
    res
)
AKonia ★★
()

Нужно поменять expt x y в коде из-за её

А конкретно-то тебе что нужно? Почему просто не кастануть x y к float?

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Почему просто не кастануть x y к float?

Не понял, это как?

А конкретно-то тебе что нужно?

У меня NaN вылетала.

saufesma
() автор топика
Ответ на: комментарий от saufesma

If x is a finite negative number and y is a finite non-integer, expt returns a NaN.

Так это насколько я понимаю для случаев когда результат - мнимое число, под это попадает -1 в степени 1/2, т.е. квадратный корень из -1, а он не определён и если хочется считать именно такое, то придётся в комплексных числах считать

AKonia ★★
()
Последнее исправление: AKonia (всего исправлений: 1)
Ответ на: комментарий от no-such-file

ну так прикол в том, что тогда придётся либо забить на такое, либо навелосипедить комплексные числа

AKonia ★★
()
Ответ на: комментарий от saufesma

Не понял, это как?

(expt (float 2) (float 3))
8.0
(expt (float -2) (float 3))
-8.0
no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Я может, что то упустил, попробуй код на лиспе, то же самое или число выдаст

[code] (defun pow (x n) (exp (* n (log x))))

(pow -2 0.3) => 0.0e+NaN

[/code]

saufesma
() автор топика
Ответ на: комментарий от saufesma

так вы логарифм от отрицательного берёте и тут при всём желании вы не придумаете действительной степени возведя в которую положительной число получится отрицательное

AKonia ★★
()
Последнее исправление: AKonia (всего исправлений: 2)
Ответ на: комментарий от saufesma

может, что то упустил

Ты упустил, что результат это не целое и даже не вещественное число. Если хочешь упороться в математику на emacs смотри сюда

no-such-file ★★★★★
()
Ответ на: комментарий от saufesma

ну так полагаю elisp он просто для другого и они выбросили поддержку комплексных, т.к. не нужно.

AKonia ★★
()
Ответ на: комментарий от no-such-file

Если хочешь упороться в математику на emacs смотри сюда

Ты намекаешь, что GNU Emacs Calculator можно использовать прям в elisp code.

saufesma
() автор топика
Ответ на: комментарий от saufesma

на clisp

То другой лисп, коммунальный. Там чего только нет, дажё чёрт в ступе. elisp сильно проще.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Программируется, класс, спасибо.

saufesma
() автор топика
Ответ на: комментарий от saufesma

можно использовать прям в elisp code.

А что мешает? Я хз что ты там делаешь, конечно.

no-such-file ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.