まず、圧縮されたコードを次に示します (回答のためにこれを行います。実際のコードでは行わないでください)。
double function(int j, int i) {
if(i == 0 || j == 1) return 1;
if(i == 1 || j == 0) return j;
if(i > 0) return j * function(j, --i);
return 1 / (function(j, -i)); //changed this to -i
//might be a division by zero, you should check for that
}
最後のブロックは、事実上、最も外側のループでのみ発生する可能性があるため、それを引き出します。
double outer_function(int j, int i) {
if (i<0)
return 1 / inner_function(j, -i);
else
return inner_function(j, i);
}
double inner_function(int j, int i) {
if(i == 0 || j == 1) return 1;
if(i == 1 || j == 0) return j;
if(i > 0) return j * inner_function(j, --i);
}
私が最初にすることは、これを末尾再帰形式にすることです。これには、再帰の後に何も来ないように方程式を再配置する必要があります。(このステップが正しかったと 100% 確信しているわけではありません)
double inner_function(int j, int i, int times=1) {
if(i == 0 || j == 1) return times;
if(i == 1 || j == 0) return times*j;
return inner_function(j, --i, times*j);
}
現在、すべてのコード パスで関数呼び出しの後にコードがないため、これは完全に末尾再帰です。末尾再帰は簡単に反復に変更できます!
double inner_function(int j, int i, int times=1) {
while(true) {
if(i == 0 || j == 1) return times;
if(i == 1 || j == 0) return times*j;
//return inner_function(j, --i, times*j);
--i;
times *= j;
//go again!
}
}
ここから最適化する場合:
double function(int j, int i) {
bool invert = false;
if(i<0) {
i=-i;
invert=true;
}
double result=1;
if(i == 0) result = 0;
else if(j == 0) result = j;
else if (j != 1) {
while(i--)
result *= j;
}
return (invert ? 1/result : result);
}
または、私があなたの意図を推測した場合:
double function(int j, int i) {
return std::pow(double(j), double(i));
}