LINUX.ORG.RU

Java - неудачная попытка перенести вычисления со стека в кучу

 ,


0

1
public class Main {

    private static int sumRec(int n) {return n>0 ? n + sumRec(n-1) : 0;}

    private static class Eval {
        public void sum() {
            if (param>0) {
                Eval e = new Eval (param-1);
                e.sum();
                rezult = param + e.rezult;
            }
            else rezult = 0;
        }
        private int param;
        public int rezult;

        Eval (int n) { param = n; }
    }

    public static void main(String[] args) {
        int n = 10000;
        //System.out.println("recursive : " + sumRec(n));
        Eval e = new Eval (n);
        e.sum();
        System.out.println("trampoline: " + e.rezult);
    }
}

Очевидные замечания, что можно посчитать в цикле или даже вспомнить Карла Фридриховича и посчитать в пару операций прошу не приводить - это все понятно, пример просто ради того, чтобы попробовать технологию, которая потом будет использоваться на нормальных задачах (если будет работать). Выдает переполнение стека. Собственно, почему? Объект через new каждый раз создается в куче, рекурсивных вызовов нет. На что расходуется стек текущего потока?

ЗЫ читал, что можно этот вычислительный объект создавать каждый раз в новом потоке, но мне хотелось бы остаться в одном. К тому же, я не знаю, как Java переварит миллион потоков, к примеру.


Ответ на: комментарий от yyk

Правильно, я вчера и наваял это:

    Func f = (Func)op;
    Object v = eval(new Env(getEvalMapArgsVals(env, f.pars, ls), f.clojure), f.body);
    while (v.getClass().getSimpleName().equals("TailCall")) {
        TailCall tc = (TailCall) v;
        v = eval(new Env(tc.args, tc.f.clojure), tc.f.body);
    }
    return v;

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

LongLiveUbuntu, да, и факториал лучше писать через цикл, мне уже сказали на предыдущей странице )

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

Да, одно только постоянное сравнение со строкой «TailCall» при каждом вызове время ест. Жабу не знаю, как быстрее посмотреть что у меня прикатилось в объекте - не в курсе, только его имя читать и со строкой сравнивать. Но у меня интерпретатор не самый быстрый, потом может ускорять буду - условия по строкам в енумы по мапам засуну и т.п. А пока главное чтобы надежно работало, да юзер интерфейс...

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

Жабу не знаю, как быстрее посмотреть что у меня прикатилось в объекте - не в курсе, только его имя читать и со строкой сравнивать.

Можно возвращать аля «енум» и просто проверять поле на null

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

Интересное утверждение. А 2+2 как лучше писать? Через двойной инкремент, инструкцию сложения, переводом в 2*2 и реализацией удвоения через побитовый левый сдвиг или сразу загрузкой константы 4 в регистр?

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

А 2+2 как лучше писать? Через двойной инкремент, инструкцию сложения, переводом в 2*2 и реализацией удвоения через побитовый левый сдвиг или сразу загрузкой константы 4 в регистр?

Так, как понятнее.

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

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