Рекурсивная ошибка возврата, Java

Итак, я определяю рекурсивную функцию, которая принимает в качестве аргумента значение x (например, арифметическую переменную x, то есть «x + 3 = 5») и возвращает результат арифметического выражения. Выражение берется из двоичного дерева выражений, которое выглядит следующим образом: введите здесь описание изображения

Вы начинаете с корня и продолжаете двигаться вниз, пока не наткнетесь на листья, и как только вы это сделаете, вы вернетесь обратно. Тогда выражение на дереве будет таким:

х * ((х + 2) + соз(х-4)).

Мой код для этой функции выглядит следующим образом:

     // Returns the value of the expression rooted at a given node
// when x has a certain value
double evaluate(double x) {
    if (this.isLeaf()) {
        //convert every instance of 'x' to the specified value
        if (this.value.equals("x")) {
            this.value = Double.toString(x);
        }
        //return the string-converted-to-double

        return Double.parseDouble(this.value);
    }
    //if-else statements to work as the arithmetic operations from the tree. Checks the given node and performs the required operation
    else {
        if(this.value.equals("sin")) { return Math.sin(evaluate(Double.parseDouble(this.leftChild.value))); }
        if(this.value.equals("cos")) { return Math.cos(evaluate(Double.parseDouble(this.leftChild.value))); }
        if(this.value.equals("exp")) { return Math.pow(evaluate(Double.parseDouble(this.leftChild.value)), evaluate(Double.parseDouble(this.rightChild.value))); }
        if(this.value.equals("*")) { return evaluate(Double.parseDouble(this.leftChild.value)) * evaluate(Double.parseDouble(this.rightChild.value)); }
        if(this.value.equals("/")) { return evaluate(Double.parseDouble(this.leftChild.value)) / evaluate(Double.parseDouble(this.rightChild.value)); }
        if(this.value.equals("+")) { return evaluate(Double.parseDouble(this.leftChild.value)) + evaluate(Double.parseDouble(this.rightChild.value)); }
        if(this.value.equals("-")) { return evaluate(Double.parseDouble(this.leftChild.value)) - evaluate(Double.parseDouble(this.rightChild.value)); }
    }
}                  

Однако компилятор выдает ошибку, говорящую мне, что моя функция должна возвращать тип double. И операторы if, и операторы else возвращают двойное значение — оператор if напрямую, а оператор else — через сумму двух двойных значений, возвращаемых одной и той же функцией. В чем здесь дело? Если я помещу оператор return за пределы if-else, то ошибка устранится сама собой, но для работы с этим мне потребуется поддерживать согласованность статической или глобальной переменной в каждой рекурсии. Я хотел бы знать, что не так с моей функцией как есть, потому что она кажется гораздо более интуитивной, чем глобальная переменная, и я думаю, что здесь отсутствует ключевая концепция рекурсии. Любая помощь приветствуется - спасибо!


person David Tamrazov    schedule 04.11.2015    source источник
comment
вам нужен последний оператор возврата на тот случай, если ничто не удовлетворяет этим ifs, поэтому просто попробуйте вернуть -1 в конце   -  person 3kings    schedule 04.11.2015


Ответы (1)


Операторы if и else возвращают двойной

На самом деле это не так. Ветвь if всегда работает, а ветвь else — нет. Что произойдет, если this.value равно "Недействительно" или чему-то другому, чего нет в вашем списке? Тогда он никогда не попадет в оператор return. Поскольку требуется всегда возвращать значение или выдавать исключение, это не разрешено.

Даже если ваша программа структурирована таким образом, что логически она всегда должна возвращать значение, компилятор не будет выполнять сложный анализ всех ветвей вашей программы, чтобы убедиться, что он всегда что-то возвращает. Он просто проверяет, что каждая ветвь имеет допустимый возврат.

Так, например, что-то вроде недопустимо

if(x < 0)  return -1;
if(x >= 0) return 1;

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

Вместо этого ваш код должен быть структурирован следующим образом:

if(x < 0) return -1;
else      return 1;

Чтобы каждая ветвь имела правильное условие выхода.

person resueman    schedule 04.11.2015
comment
Ааа, ладно, мне нужно добавить в конец предложение else, чтобы всегда возвращалась какая-то форма двойника, да? Также мне пришло в голову, что весь блок намного чище, чем оператор switch, так что включение случая по умолчанию, который возвращает значение ошибки, дважды решит мою проблему? Или мне все еще нужно включить какое-то условие проверки исключений для каждой арифметической операции? - person David Tamrazov; 04.11.2015
comment
@DavidTamrazov Если вы используете switch с default, это будет работать нормально. Вы также всегда можете поставить return в конце функции, чтобы вернуть значение по умолчанию (или, возможно, создать исключение, если не думаете, что оно когда-либо должно достичь этой точки). Важно помнить, что каждая ветвь (даже если вы знаете, что этого никогда не произойдет) должна иметь либо return, либо throw. - person resueman; 04.11.2015