“主要问题就是在NestWhile上面”……你哪来的自信啊?我们把这一块去掉看看:
cf = Compile[{a, z},
Which[z <= 0, a^z - 2, 0 < z <= 1, z - 1(*,z>1,Block[{i=-1},NestWhile[Log[a,#]&,
z,(i++;#>1)&]-1+i]*)]]
CompilePrint@cf
(*照样MainEvaluate*)
于是乎为什么会这样呢?在这篇教程的规则四里我已经提到了,Compile内的变量类型不能中途改变,并且在很多情况下,Compile的某些看似古怪的行为骨子里都和这有关,而这里Which的失效就属于这种情况。我们回忆一下Which的语法,如果Which内的全体条件都不能返回True,它的返回值是啥?0吗?不对,是Null。
这就导致了Which语句的返回值出现了不确定的情况(以你的例子而言,其他情况下Which的返回值的类型是Real),于是,编译失败。修改方法很简单,让全体返回值的类型一致就行了:
cf2 = Compile[{a, z},
Which[z <= 0, a^z - 2, 0 < z <= 1, z - 1, z > 1,
Block[{i = -1}, NestWhile[Log[a, #] &, z, (i++; # > 1) &] - 1 + i], True, 0.]]
这个问题还可以参看这帖。