Реализация Мандельброта в Common Lisp

echo htmlentities("<label> AAAAA");
11
задан Glorfindel 3 June 2019 в 04:06
поделиться

2 ответа

Я не уверен, что эта часть правильная:

        (setq tmpcplx (+ (* (* tmpreal tmpcplx) 2) cplx))
        (setq tmpreal (+ (- (* tmpreal tmpreal) (* tmpcplx tmpcplx))
           real))

не Tempcplx Будучи перезаписываемым своим новым значением на первой строке, что означает, что вторая строка использует новое значение, а не оригинальный?

в версии Python, вы избегаете этой проблемы с помощью TMPB:

  tmpb = tmpcplx
  tmpcplx = tmpreal*tmpcplx*2
  tmpreal = tmpreal*tmpreal - tmpb*tmpb
  tmpcplx += cplx
  tmpreal += real

, кажется, Мне версия Lisp должна делать что-то похожее, то есть сначала хранить исходное значение TMPCPLX и использовать этот магазин для расчета TMPreal:

        (setq tmpb cplx)
        (setq tmpcplx (+ (* (* tmpreal tmpcplx) 2) cplx))
        (setq tmpreal (+ (- (* tmpreal tmpreal) (* tmpb tmpb))
           real))
5
ответ дан 3 December 2019 в 08:04
поделиться

Некоторые замечания о вашем коде:

  • Mandelbrot: не хватает деклараций, квадраты вычисляются дважды в цикле

  • Mandelbrot: в вычислении для Tmpreal вы используете новое значение TMPCLX, не старый

  • , вы не хотите использовать методы для установки пикселей. МЕДЛЕННЫЙ.

  • Floordiv является одним из пола или усечений (в зависимости от того, что вы хотите) в общем Lisp, см. (Этаж 10 3)

  • Использование типа Декларации

  • в WhicleXBM Не повторяйте данные и стремиться

  • SetPixel UnetPixel выглядит очень дорогим, снова неоднократно разыгравшимся структурой

  • Draw-Mandelbrot имеет много повторных вычислений, которые могут быть сделаны один раз

  • Common Lisp, имеет 2D-массивы, которые упрощают код

  • Common Lisp имеют комплексные числа, которые имеют комплексные номера, которые Также упростите код

  • Имя переменной «Self» не имеет смысла в общем лиспе. Назовите его к тому, что это так.

Обычно код полон отходов. Это имеет мало смысла показывать ваш код, поскольку он написан в стиле, который, надеюсь, никто не использует в общем Lisp. Common Lisp был разработан с опытом большого математического программного обеспечения, такого как Macsyma, и позволяет писать математический код прямо вперед (без объектов, просто функций по номерам, массивам, ...). Лучшие компиляторы могут воспользоваться преимуществами примитивных типов, примитивных операций и типовых деклараций. Таким образом, стиль отличается от того, что можно написать в Python (который обычно либо ориентирован на объектно-ориентированные Python или звонки на некоторые C-код) или Ruby. В тяжелом численном коде, как правило, не очень хорошая идея иметь динамическую отправку, как с закрытыми. Настройка пикселей в растровых изображениях с помощью закрытых вызовов в тесной петле - это действительно то, что нужно избегать (если вы не знаете, как его оптимизировать).

Лучшие компиляторы Lisp скомпилируют числовые функции для прямого машинного кода. Во время компиляции они дают подсказки, которые операции являются общими и не могут быть оптимизированы (пока разработчик не добавит больше информации о типе). Разработчик также может «разобрать» функции и проверять код, который является обзором или ненужные вызовы функций. «Время» дает информацию о времени выполнения, а также информирует разработчику о количестве памяти «Сосредоточенность». В числовом коде, кончикам «Floats» - это обычная задача производительности.

Итак, для суммирования:

  • Если вы пишете код И подумайте, что он делает то же самое на разных языках, когда код выглядит похоже или имеет аналогичную структуру, это может быть не так - если вы действительно не знаете оба языка, так и оба языковых реализация.

  • Если вы пишете код на одном языке И портируйте его в аналогичный стиль на другой язык, вы можете пропустить целую существующую культуру, чтобы написать решения подобных проблемах по-другому. Например, можно написать код в C ++ в объектно-ориентированном стиле и портируйте его в Аналогичный путь к Фортрю. Но никто не пишет такой код в Фортране. Написано в стиле Fortran, обычно приведет к более быстрому коду - тем более, что компиляторы сильно оптимизированы для идиоматического кода Fortran.

  • », когда в Риме говорите Римлянам "

Пример:

в setpixel там звонок (сначалаDim Self)). Почему бы не сделать это значение слота в структуре в первую очередь, вместо того, чтобы сделать доступ к списку все время? Но тогда значение постоянна во время вычисления. Тем не менее, структура пропускается, и значение получено все время. Почему бы не просто получить значение за пределами основного цикла и пропустите его напрямую? Вместо того, чтобы делать несколько вычислений этого?

, чтобы дать вам представление о том, как код может быть написан (с типовыми объявлениями, петлями, комплексными числами, ...), вот немного другой версии вычисления Mandelbrot.

Основной алгоритм:

(defvar *num-x-cells* 1024)
(defvar *num-y-cells* 1024)
(defvar *depth* 60)


(defun m (&key (left -1.5) (top -1.0) (right 0.5) (bottom 1.0) (depth *depth*))
  (declare (optimize (speed 3) (safety 0) (debug 0) (space 0)))
  (loop with delta-x-cell float = (/ (- right left) *num-x-cells*)
        and  delta-y-cell float = (/ (- bottom top) *num-y-cells*)
        and field = (make-array (list *num-x-cells* *num-y-cells*))
        for ix fixnum below *num-x-cells*
        for x float = (+ (* (float ix) delta-x-cell) left)
        do (loop for iy fixnum below *num-y-cells*
                 for y = (+ (* (float iy) delta-y-cell) top)
                 do (loop for i fixnum below depth
                          for z of-type complex = (complex x y)
                          then (+ (complex x y) (* z z))
                          for exit = (> (+ (* (realpart z) (realpart z))
                                           (* (imagpart z) (imagpart z)))
                                        4)
                          finally (setf (aref field ix iy) i)
                          until exit))
        finally (return field)))

Вышеуказанные функции возвращает 2D массив чисел.

Написание файла XBM:

(defun writexbm (array pathname &key (black *depth*))
  (declare (fixnum black)
           (optimize (speed 3) (safety 2) (debug 0) (space 0)))
  (with-open-file (stream pathname :direction :output :if-exists :supersede)
    (format stream "#define mandelbrot_width ~d~&"  (array-dimension array 0))
    (format stream "#define mandelbrot_height ~d~&" (array-dimension array 1))
    (format stream "#define mandelbrot_x_hot 1~&")
    (format stream "#define mandelbrot_y_hot 1~&")
    (format stream "static char mandelbrot_bits[] = {")
    (loop for j fixnum below (array-dimension array 1) do
          (loop for i fixnum below (truncate (array-dimension array 0) 8)
                for m fixnum = 0 then (mod (1+ m) 8) do
                (when (zerop m) (terpri stream))
                (format stream "0x~2,'0x, "
                        (let ((v 0))
                          (declare (fixnum v))
                          (dotimes (k 8 v)
                            (declare (fixnum k))
                            (setf v (logxor (ash (if (= (aref array
                                                              (+ (* i 8) k) j)
                                                        black)
                                                     1 0)
                                                 k)
                                            v)))))))
    (format stream "~&}~&")))

Вышеуказанные функции принимают массив и путь и записывают массив в виде файла XBM. Один номер «черный» будет «черным», а остальные номера «белые»

Call

(writexbm (m) "/tmp/m.xbm")
10
ответ дан 3 December 2019 в 08:04
поделиться
Другие вопросы по тегам:

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