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

Ответить
razmus
Сообщения: 82
Зарегистрирован: 26 мар 2013, 10:47

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

Сообщение razmus » 16 янв 2015, 11:19

Здравствуйте, написал простенький калькулятор, но не пойму по чему он крешит, в логике проблемы не вижу.
Вылетает постоянно с ошибкой Invalid index 1, size is 1 (для ArrayList). Но дело в том, что while уже передано значение false и он по всем законам логики не должен запуститься еще раз. Даже попытка поставить дополнительную проверку if (mathMap.size() != 1) не приводит ни к чему, она просто игнорируется.
Может кто глянуть код и сказать. Заранее благодарен!

З.Ы.
Прикрепил файл проекта.

Код: Выделить всё

    int openB = 0;
    int closeB = 0;
    String math = "1+(2*3/4+5)+6+(7+8)";
    String result = "";
    ArrayList<String> mathMap = new ArrayList<String>();

        parse(math);
        while (findBeakets()) {
            while (findDivMul())
                ;
            while (findAddSub())
                ;
        }
        readList();


    public void parse(String s) {
        for (int i = 0; i < s.length(); i++) {
            if (Character.isDigit(s.charAt(i))) {
                mathMap.add(String.valueOf(s.charAt(i)));
            } else {
                mathMap.add(String.valueOf(s.charAt(i)));
            }
        }
    }
    
    public void readList() {
        for (int i = 0; i < mathMap.size(); i++) {
            result += mathMap.get(i);
        }
        Log.d("TAG", result);
        result = "";
    }
    
    public boolean findBeakets() {
        for (int i = 0; i < mathMap.size(); i++) {
            if (mathMap.get(i).equals("(")) {
                openB = i;
            }
            if (mathMap.get(i).equals(")")) {
                closeB = i;
                if ((closeB - openB) == 2) {
                    mathMap.remove(openB);
                    mathMap.remove(closeB - 1);
                    findBeakets();
                }
                return true;
            }
        }
        openB = 0;
        closeB = mathMap.size();
        return false;
    }
    
    public void delElement(int i) {
        mathMap.remove(i - 1);
        mathMap.remove(i);
        closeB = closeB - 2;
    }
    
    public boolean findDivMul() {
        if (mathMap.size() != 1) {
            for (int i = openB; i < closeB; i++) {
                if (mathMap.get(i).equals("/")) {
                    mathMap.set(i, ((Integer.parseInt(mathMap.get(i - 1))) / (Integer.parseInt(mathMap.get(i + 1)))) + "");
                    delElement(i);
                    findDivMul();
                }
                if (mathMap.get(i).equals("*")) {
                    mathMap.set(i, ((Integer.parseInt(mathMap.get(i - 1))) * (Integer.parseInt(mathMap.get(i + 1)))) + "");
                    delElement(i);
                    findDivMul();
                }
            }
        }
        return false;
    }
    
    public boolean findAddSub() {
        if (mathMap.size() != 1) {
            for (int i = openB; i < closeB; i++) {
                if (mathMap.get(i).equals("+")) {
                    mathMap.set(i, ((Integer.parseInt(mathMap.get(i - 1))) + (Integer.parseInt(mathMap.get(i + 1)))) + "");
                    delElement(i);
                    findAddSub();
                }
                if (mathMap.get(i).equals("-")) {
                    mathMap.set(i, ((Integer.parseInt(mathMap.get(i - 1))) - (Integer.parseInt(mathMap.get(i + 1)))) + "");
                    delElement(i);
                    findAddSub();
                }
            }
        }
        return false;
    }
Вложения
calc.rar
(664.82 КБ) 157 скачиваний

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение altwin » 16 янв 2015, 12:03

Если вы хотите научиться чему -то -учитесь, а не ищите ошибке в компиляторе используемом десятки лет миллионами. Даже код смотреть не нужно, что означат строка ошибки - Invalid index 1, size is 1 ?
У вас есть массив из одного элемента -int[] arr = { Integer }, значение length которого == 1. А теперь включаем логику и думаем, что будет если к этому массиву обратиться по индексу 1 ( arr[1] === ??? ).
Изображение

razmus
Сообщения: 82
Зарегистрирован: 26 мар 2013, 10:47

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение razmus » 16 янв 2015, 12:11

altwin писал(а):Если вы хотите научиться чему -то -учитесь, а не ищите ошибке в компиляторе используемом десятки лет миллионами. Даже код смотреть не нужно, что означат строка ошибки - Invalid index 1, size is 1 ?
У вас есть массив из одного элемента -int[] arr = { Integer }, значение length которого == 1. А теперь включаем логику и думаем, что будет если к этому массиву обратиться по индексу 1 ( arr[1] === ??? ).
Отладчиком я пользоваться умею. И как работает индексация в массивах, векторах.... Вы не прочитали того что я написал, а сделали вывод, что я олененок. Где падает я знаю, я не могу понять почему. while(false), что произойдет? цикл остановится. Но в этом случае, он по не понятной мне причине продолжает вызываться и рекурсия продолжается, по тому и падает. Так же мне совершенно не понятно, почему установленные условия выполнения рекурсии игнорируются также. Хотя судя по логу, условия правильные и поступающие значения тоже.

З.Ы.
Программку я написал просто от нефиг делать, раскапывал исходники и нашел, похожее на с++ 10-й давности.

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение altwin » 16 янв 2015, 12:23

Во первых я не много не понял при чем тут отладчик. Если вы поимаете, как работает индексация массива, то вам не следует не только так часто использовать слово рекурсия по отношению к операции итерации (поскольку это абсолютно не верно) но и понимать что в случае обращения к не существующему индексу массива вы получаете не false а ошибку. Но даже если опустить то, что вы все знаете и уверенны в своих способностях, даже знаете что такое рекурсия (хоть она тут вообще отсутсвует) объясните откуда вам в while приходит false? Ваш метод findBeakets() содержит цикл в котором вы скорее всего и обращаетесь к не существующему индексу и он ничего не возвращает, он выбрасывает ошибку и все пропало... ;)

p.s. и да при не выполнении условия цикла, его тело игнорируется, варриантов тут нет.
Изображение

razmus
Сообщения: 82
Зарегистрирован: 26 мар 2013, 10:47

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение razmus » 16 янв 2015, 12:30

"Рекурсия в программировании - это когда метод вызывает сам себя. В таком случае метод называют рекурсивным." Мне кажется вы не знаете, что это) загляните в любой учебник.
Я понимаю, что если лезть за пределы массива будет ошибка). Да вот таки лезу правильно. Когда наступает время полезть не туда все должно закончится.
Я в курсе что при не выполненный условий игнорируется, они для того и созданы.

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение altwin » 16 янв 2015, 12:39

razmus писал(а):"Рекурсия в программировании - это когда метод вызывает сам себя. В таком случае метод называют рекурсивным." Мне кажется вы не знаете, что это) загляните в любой учебник.
Я понимаю, что если лезть за пределы массива будет ошибка). Да вот таки лезу правильно. Когда наступает время полезть не туда все должно закончится.
Я в курсе что при не выполненный условий игнорируется, они для того и созданы.
Ок я повторю для особо одаренных - у вас в коде нет рекурсии. Метод не вызывает сам себя, он вызывается итератором. Также наверно стоит повторить, что ваша ошибка говорит абсолютно четко - вы обращаетесь к не существующему индуксу массива. Когда все должно закончиться - оно заканчивается. В дальнейших коментариях не вижу смысла и спорить с дилетантами не привык, удачи ;)
Изображение

razmus
Сообщения: 82
Зарегистрирован: 26 мар 2013, 10:47

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение razmus » 16 янв 2015, 12:39

2
Последний раз редактировалось razmus 16 янв 2015, 12:46, всего редактировалось 1 раз.

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение altwin » 16 янв 2015, 12:45

razmus писал(а):Падение происходит

Код: Выделить всё

    public boolean findAddSub() {
//еще раз проверяю один ли там? да один 
        if (mathMap.size() != 1) { //а вот и не один, так как условие выполнятеся
            for (int i = openB; i < closeB; i++) { 
                if (mathMap.get(i).equals("+")) { 
                    mathMap.set(i, ((Integer.parseInt(mathMap.get(i - 1))) + (Integer.parseInt(mathMap.get(i + 1)))) + ""); 
                    delElement(i);
//элементы удалились и размер стал 1, читаю получаю значение
                    findAddSub(); 
                } 
                if (mathMap.get(i).equals("-")) { 
                    mathMap.set(i, ((Integer.parseInt(mathMap.get(i - 1))) - (Integer.parseInt(mathMap.get(i + 1)))) + ""); 
                    delElement(i); 
                    findAddSub(); 
                } 
            } 
        } 
Знаете в такой ситуации я начинаю переживать за свою психику.. я же с живым человеком общаюсь не со стенкой?? Вы проверяте что массив содержит минимум 1 элемент? Ок повторю - ваша ошибка говорит о том, что ваш массив содержит один элемент! Что вы проверяете еще??? Только вторая часть сообщения об ошибке говорит о том, что вы к этому элементу обращаете по индексу 1. А индекс массива из 1 элемента равен 0.
Если элемент не один и выполняется другое условие, то вы получили другую ошибку, поскольку сменили условие. Либо ошибка в другом месте, значения это не имеет. Сообщение об ошибке четкое и однозначное, варриантов тут нет.

Тут вообще что угодно может быть. вы на вход методу можете просто дать строку без закрывающейся скобки и он у вас вывалится с той же ошибкой, поскольку вызвав findBeakets уже внутри цикла для поиска закрывающей -ее нет. И вернутся не false, а ошибка, поскольку вы не проверяете ничего, вы просто обращаетесь к элементу с уверенностью, что он передан.
Т.е. вот это - if (mathMap.get(i).equals(")")) * в случае отсутсвия i - выбросит ошибку, у вас их понатыканно везде и где эта ошибка я к примеру понятия не имею, проверять нужно все входящие данные.

P.S> если вам нужно найти закрывающуюся скобку, гораздо логичнее запускать вложенный цикл с позиции открытой, но никак не городить все это. Либо же в случае out of place алгоритма нужно использовать внешний стек дял сохранения результатов.
Последний раз редактировалось altwin 16 янв 2015, 12:54, всего редактировалось 1 раз.
Изображение

razmus
Сообщения: 82
Зарегистрирован: 26 мар 2013, 10:47

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение razmus » 16 янв 2015, 12:53

Знаете я тоже в такой ситуации начинаю переживать за свою психику. Вы не желаете разбираться и в тонкостях, а машете лопатой, не хотите отвечать не нужно, я вас не прошу о этом. Мне ситуация показалась забавной, по тому и выложил код. Индекс равен 0, а размер 1, это две большие разници. Условие и стоит для того чтобы никуда уже не адресоваться. "Давайте дилетантами тут не кидаться, будьте добры", явой я занимаюсь не так давно, но с другими языками дружу уже давно.

З.Ы.
Я так написал программу специально, интересно было что получится.
Последний раз редактировалось razmus 16 янв 2015, 12:56, всего редактировалось 1 раз.

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение altwin » 16 янв 2015, 12:56

razmus писал(а):Знаете я тоже в такой ситуации начинаю переживать за свою психику. Вы не желаете разбираться и в тонкостях, а машете лопатой, не хотите отвечать не нужно, я вас не прошу о этом. Мне ситуация показалась забавной, по тому и выложил код. Индекс равен 0, а размер 1, это две большие разници. Условие и стоит для того чтобы никуда уже не адресоваться. "Давайте дилетантами тут не кидаться, будьте добры"

З.Ы.
Я так написал программу специально.
Invalid index 1, size is 1
еще вопросы?

Я повторю еще раз, ошибка абсолютно однозначна.

Раз уж вы так написали специально, вот именно то, что получилось :) Я бы вам предложил запустить это с выражением со вложенными скобками, еще повеселитесь )) На самом деле хотите решение - полностью переписывайте. Тут все не верно, и не оптимально, если вы сделали это специально - ждите когда придет тот, кто захочет разбираться в коде не правильно решающем стандартную задачу.
Последний раз редактировалось altwin 16 янв 2015, 13:00, всего редактировалось 1 раз.
Изображение

razmus
Сообщения: 82
Зарегистрирован: 26 мар 2013, 10:47

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение razmus » 16 янв 2015, 12:58

Ошибка и в правду однозначна, выход за границу

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение altwin » 16 янв 2015, 13:02

razmus писал(а):Ошибка и в правду однозначна, выход за границу
Просто не создавайте себе проблем, перед каждым обращением к элементу массива добавите проверку на его существование. Один из наиболее важных принципов - проверять все входящие данные.

P.S. и да выражения могут быть еще такими - 1+(( 2*3 )/4+5)+6+(7+8), можете не запуская сказать, что ваш код тут скажет? ). Опять же на шаг ближе к ответу на вопросы которые возникнут в будущем.
Изображение

razmus
Сообщения: 82
Зарегистрирован: 26 мар 2013, 10:47

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение razmus » 16 янв 2015, 13:10

altwin писал(а):
razmus писал(а):Ошибка и в правду однозначна, выход за границу
Просто не создавайте себе проблем, перед каждым обращением к элементу массива добавите проверку на его существование. Один из наиболее важных принципов - проверять все входящие данные.

P.S. и да выражения могут быть еще такими - 1+(( 2*3 )/4+5)+6+(7+8), можете не запуская сказать, что ваш код тут скажет? ). Опять же на шаг ближе к ответу на вопросы которые возникнут в будущем.
Хотите посмеяться, а на выражении 1+((2*3)/4+5)+6+(7+8) все посчитало верно) так как алгоритм учитывает вложенные скобки. Забавно то что на предыдущем нет. "Пробелы убрал специально, так как проверки на неправильные символы нет".

З.Ы.
Предыдущий тоже стало нормально считать, видо заглючило эмулятор.

З.З.Ы.
Хотя нет, я перед ретурном в findAddSub(), для контроля добавил readList(); И тогда работает, а если убрать то нет. "Может где-то куча валится...."

Аватара пользователя
altwin
Сообщения: 1951
Зарегистрирован: 13 ноя 2013, 14:46

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение altwin » 16 янв 2015, 13:30

razmus писал(а):
altwin писал(а):
razmus писал(а):Ошибка и в правду однозначна, выход за границу
Просто не создавайте себе проблем, перед каждым обращением к элементу массива добавите проверку на его существование. Один из наиболее важных принципов - проверять все входящие данные.

P.S. и да выражения могут быть еще такими - 1+(( 2*3 )/4+5)+6+(7+8), можете не запуская сказать, что ваш код тут скажет? ). Опять же на шаг ближе к ответу на вопросы которые возникнут в будущем.
Хотите посмеяться, а на выражении 1+((2*3)/4+5)+6+(7+8) все посчитало верно) так как алгоритм учитывает вложенные скобки. Забавно то что на предыдущем нет. "Пробелы убрал специально, так как проверки на неправильные символы нет".

З.Ы.
Предыдущий тоже стало нормально считать, видо заглючило эмулятор.
Я конечно рад за вас, но, вы не можете из метода findBeakets описанного в вопросе найти ничего кроме скобок тут - (2*3). Вы либо будете находить их всегда получая true, либо получите бесконечный цикл, поскольку повторно запуская ту же функцию входящие данные не меняются и результат тот же. Похоже вы действительно решаете очень спецефическую задачу, по какому -то магическому алгоритму )) Во всех примерах применения, которые я могу представить это просто не может работать. Либо ваш код сильно отличается от примера :D
Изображение

razmus
Сообщения: 82
Зарегистрирован: 26 мар 2013, 10:47

Re: Подозрение на баг в компиляторе, проверьте кто может

Сообщение razmus » 16 янв 2015, 13:40

Находит все) так как всегда ищет с начала, после удаления скобок в которых найдено решение. И именно по тому, что это рекурсия). Специфическая задача... да заняться сейчас нечем, вот решил дуростями пострадать))

Код: Выделить всё

while (findBeakets()) { 
            while (findDivMul()) 
                ; 
            while (findAddSub()) 
                ; 
        } 

Ответить