int f(int n, int mul) {
if (abs(n)%mul == 0) return n;
else return f(n - 1, mul);
}
所以它向下舍入到下一个mul
。但显然对n的大值不好。如何安全有效地表达?
答案 0 :(得分:5)
这相对简单,您只需在调整变量时评估变化的表达式,直到结果满足正确的条件:
while (abs(n) % mul != 0) --n;
注意:
abs()
看起来很无辜,但是如果你在二进制补码系统中给出最小的整数呢?根本没有绝对值可以表示为这样的整数。n
可能会下溢,从而导致未定义的行为(以及令人惊讶的结果)。mul
不是正面怎么办?代码不以任何方式处理这种情况,而函数签名允许它。答案 1 :(得分:4)
RE
“如何安全有效地表达[递归函数]?
对于非负n
和mul
,您可以这样做
return n - n%mul;
我将可能的负值调整以及如何处理零mul
给读者。
这和你能得到的效率差不多;它是欧几里德会使用的,如果他今天活着并使用C ++而不是 [1] COBOL。
另一种选择是
return mul*(n/mul);
是否比第一种效率更高或更低,取决于。
但是,我认为任何差异都不会太小。
你并不是要求最有效率,而只是“有效率”。这意味着合理的效率。只要有效率,我仍然建议测量。
测量需要不需要很大的努力。
在许多情况下,只是观察程序运行得相当好,可以是一个足够好的测量(分辨率和精度非常低,但通常足够好)。
[1] 不确定为什么,但我总是认为欧几里德是一个COBOL家伙。 功能
答案 2 :(得分:0)
如果你担心StackOverflow
......那就不要了!
以下函数基本上是tail recursive
函数,像GCC这样的编译器会自动将它转换为迭代函数!
int f(int n, int mul) {
if (abs(n)%mul == 0) return n;
return f(n - 1, mul); //Tail recursion
}
REF:
希望这有帮助!
答案 3 :(得分:0)
如果您的第二个参数是如此,它只会舍入到100。接下来是迭代实现。如果您提供更多详细信息,我可能会再次查看。
int f(int n, int mul)
{
while(n%mul != 0)
{
n--;
};
return n;
}
答案 4 :(得分:0)
其他哪些用户建议或多或少地为n
的有限案例工作。
一般案例的解决方案在哪里:
if (abs(n) % mul == 0)
return n;
else if (n >= 0)
return n - abs(n) % mul;
else
return mul - abs(n) % mul;
或者首选oneliner
return abs(n) % mul == 0 ? n : n - (n >= 0 ? abs(n) % mul : mul - abs(n) % mul);