【问题标题】:Why does my fast exponentiation algorithm give me a 'cannot find symbol' error in the parameter of a lambda?为什么我的快速求幂算法在 lambda 参数中出现“找不到符号”错误?
【发布时间】:2019-09-27 05:51:59
【问题描述】:

我正在努力实现的背景/目标:

我正在尝试从头开始在 Java 中实现快速求幂算法(作为实践)。算法如下(解释取自johndcook.com):

输入:底数b,指数n

将指数 n 写成二进制。从左数第二位开始,从左到右读取二进制表示。从数字 a 开始,每次读取 0 位时,求平方。每次读取 1 位时,将所得到的平方并乘以 a。因此,可以使用不超过 2 个 log2(n) 乘法来计算 an。

我不是在寻找更好的方法来实现这个算法,而是为什么我会得到这个特定的错误。

问题是什么

我尝试在Java中使用递归lambda来实现这个算法,当我去运行程序时,我得到了以下错误:

Main.java:11: 错误:找不到符号

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

Main.java:11: 错误:这里不需要 lambda 表达式

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

【问题讨论】:

  • Labdas 无法引用自己。
  • 使用常规方法即可。
  • 将 lambda 作为参数传递。
  • 作为 lambda 的参数。
  • 在 Java 中没有没有类型的内联 lambda。 Java 不是 JavaScript。在 Java 中,您需要像 Function<Integer, Integer> f = x -> x + 1; 这样的东西,一旦您拥有 Function 类型的变量,您将使用 Integer b = f.apply(42); 调用。

标签: java algorithm lambda parameters compiler-errors


【解决方案1】:

您遇到的一个主要问题是您的 lambda 没有类型。你需要给它一个。我不知道java.util.function 中有任何类型可以表示一个带有 4 个参数的函数,因此您可能需要自己声明此类型。

另一个主要问题是您在其声明中使用了变量exponentiator,这是无效的。要解决此问题,您需要向 lambda 添加第五个参数,lambda 本身将传递给该参数。然后,您将用对该参数的调用替换递归调用。

让我们先声明代表这个 lambda 的类型。

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);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多