Почему мой алгоритм быстрого возведения в степень дает мне ошибку «не удается найти символ» в параметре лямбды? - PullRequest
2 голосов
/ 27 сентября 2019

Справочная информация / Цель, которую я пытаюсь выполнить:

Я пытаюсь реализовать алгоритм быстрого возведения в степень в Java с нуля (на практике).Алгоритм выглядит следующим образом (объяснение взято с johndcook.com):

Ввод: база b , показатель степени n .

Запись показателя nв двоичномПрочитайте двоичное представление слева направо, начиная со второго бита слева.Начните с цифры a, и каждый раз, когда вы читаете 0 бит, возведите в квадрат то, что у вас есть.Каждый раз, когда вы читаете 1 бит, возведите в квадрат то, что у вас есть, и умножьте на.Отсюда следует, что an может быть вычислено с использованием не более 2 log2 (n) умножений.

Я не ищу лучшего способа реализации этого алгоритма, а скорее почему я получаю эту конкретную ошибку.

В чем проблема

Я пытался реализовать этот алгоритм, используя рекурсивную лямбду в Java, и когда я запустил программу, я получил следующие ошибки:

Main.java: 11: ошибка: не удается найти символ

exponentiator = (int runningResult, int binLength, int binInt, int expBase) -> {
                                                               ^

Main.java: 11: ошибка: лямбда-выражение здесь не ожидается

exponentiator = (int runningResult, int binLength, int binInt, int expBase) -> {
^

Main.Java: 23: ошибка: не могу найти символ

exponentiator(b, length, nBinInt, b);
^

У меня нет объяснения этим ошибкам, кто-нибудь может мне помочь?

Код:

class Main {
  public static void main(String[] args) {
    fastExp(2, 13);
  }
  //This is the algorithm itself
  public static int fastExp(int b, int n) {
    //converts n (b^n) to binary for algorithm
    String nBinStr = Integer.toBinaryString(n);
    int nBinInt = Integer.parseInt(nBinStr);
    int length = String.valueOf(nBinInt).length();
    exponentiator = (int runningResult, int binLength, int binInt, int expBase) -> {
      int firstDigit = Integer.parseInt(Integer.toString(binInt).substring(1, 2));
      if(binLength = 0){
        return runningResult;
      }
      else if(firstDigit = 0){
        exponentiator((runningResult * runningResult), (binLength - 1), (binInt % (int) Math.pow(10, (int) Math.log10(binInt))), expBase);
      }
      else {
      exponentiator((runningResult * runningResult * base), (binLength - 1), (binInt % (int) Math.pow(10, (int) Math.log10(binInt))), expBase);
      }
    };
    exponentiator(b, length, nBinInt, b);
  }
}

https://repl.it/@Jodastt/Fast-Exponentiation

1 Ответ

1 голос
/ 27 сентября 2019

Одна из основных проблем, с которой вы столкнулись, заключается в том, что ваша лямбда не имеет типа.Вы должны дать это один.Мне не известны какие-либо типы в java.util.function, которые могут представлять функцию, принимающую 4 параметра, поэтому вам, вероятно, нужно объявить этот тип самостоятельно.

Другая важная проблема заключается в том, что вы используете переменную exponentiatorвнутри декларации, которая недействительна.Чтобы обойти это, вам нужно добавить пятый параметр в вашу лямбду, которому будет передаваться сама лямбда.Затем вы замените рекурсивные вызовы вызовами этого параметра.

Давайте сначала объявим тип, представляющий эту лямбду.

interface IntQuadRecursiveFunction {
    int apply(int a, int b, int c, int d, IntQuadRecursiveFunction f);
}

И затем exponentiator можно переопределить так:

// note the type and extra parameter "f"
IntQuadRecursiveFunction exponentiator = (runningResult, binLength, binInt, expBase, f) -> {
   int firstDigit = Integer.parseInt(Integer.toString(binInt).substring(1, 2));
   if (binLength == 0) { // It's "==", not "="
       return runningResult;
   } else if (firstDigit == 0) {
        // note the word "return", which you were missing
        // also the extra argument "f"
       return f.apply((runningResult * runningResult), (binLength - 1), (binInt % (int) Math.pow(10, (int) Math.log10(binInt))), expBase, f);
   } else {
       // should be "expBase", not "base"
       return f.apply((runningResult * runningResult * expBase), (binLength - 1), (binInt % (int) Math.pow(10, (int) Math.log10(binInt))), expBase, f);
   }
};

использование:

// you are missing a return in "fastExp" as well
return exponentiator.apply(b, length, nBinInt, b, exponentiator); // note the last argument

Если честно, на вашем месте я бы просто спас все эти неприятности и вместо этого написал бы обычный метод:

public static int fastExp(int b, int n) {
    //converts n (b^n) to binary for algorithm
    String nBinStr = Integer.toBinaryString(n);
    int nBinInt = Integer.parseInt(nBinStr);
    int length = String.valueOf(nBinInt).length();
    return exponentiator(b, length, nBinInt, b);
}

private static int exponentiator(int runningResult, int binLength, int binInt, int expBase) {
    int firstDigit = Integer.parseInt(Integer.toString(binInt).substring(1, 2));
    if (binLength == 0) { 
        return runningResult;
    } else if (firstDigit == 0) {
        return exponentiator((runningResult * runningResult), (binLength - 1), (binInt % (int) Math.pow(10, (int) Math.log10(binInt))), expBase);
    } else {
        return exponentiator((runningResult * runningResult * expBase), (binLength - 1), (binInt % (int) Math.pow(10, (int) Math.log10(binInt))), expBase);
    }
}
...