我正在编写一个示例程序来测试Tool语言的编译器。 Here您可以找到该语言的一些文档。我的程序代码如下:
program CountChange {
println(new countChangeApp().initCoins().countChange(300));
}
class countChangeApp{
var array: Int[];
def initCoins() :countChangeApp = {
array = new Int[7];
array[0] = 5;
array[1] = 10;
array[2] = 20;
array[3] = 50;
array[4] = 100;
array[5] = 200;
array[6] = 500;
return this;
}
def countChange(money:Int):Int = {
return this.computeCountChange(money,array);
}
def computeCountChange(money: Int,coins :Int[]): Int = {
var answer : Int;
if (money < 0 || coins.length == 0) answer = 0;
else if (money == 0) answer = 1;
else answer = this.computeCountChange(money-coins[0],coins) + this.computeCountChange(money,this.tail(coins));
return answer;
}
def tail(array: Int[]): Int[] = {
var tail : Int[];
var i : Int;
if(0 < array.length){
tail = new Int[array.length - 1];
i = 0;
while(i < array.length - 2){
tail[i] = array[i+1];
i = i+1;
}
}else{
tail = new Int[array.length];
}
return tail;
}
}
所以基本上,计算方法的数量可以用硬币大小5,10,20,50,100,200和500来改变300.
我还彻底测试了底部出现的尾部功能,这不应该是我们关注的问题。
问题在于,当我执行它(遵循this指令)时,我得到一个令人讨厌的StackOverflowError形式:
Exception in thread "main" java.lang.StackOverflowError
at countChangeApp.computeCountChange(countchange.tool:29)
最后一行重复多次。我的猜测是,我可能会为阵列保留太多的内存。有谁看到问题可能是什么?
答案 0 :(得分:1)
我的猜测是,我可能会为阵列保留过多的内存。
从错误消息判断,您的语言正在JVM上运行。 JVM从不在堆栈上存储数组,因此大型数组不会导致堆栈溢出。
tail = new Int[array.length - 1]; i = 0; while(i < array.length - 2){ tail[i] = array[i+1]; i = i+1; }
您正在创建一个n-1个元素的数组,但只会在其中编写n-2个元素。所以最后一个元素将是0。
就你的改变计数逻辑而言,这意味着你有一个0值硬币。这意味着一旦你达到那个0值硬币,当你money-coins[0]
时,你就会得到完全相同的金钱,导致无限递归。并且禁止尾递归优化(这不适用于此函数,因为函数不是尾递归),无限递归总是会导致堆栈溢出。