问题描述
最近我被派去做一个递归函数,该函数仅使用加法(不允许减法)进行除法,并且只有两个变量。
编辑:基于注释的一些注释:
-
n1除以n2。 (n1:n2)
-
答案应该是整数(整数),表示您可以将n2放入n1的次数(8:3应该得到2,8:4也应该得到2)。
-
您可以假定输入只是整数正数。
按照评论中的要求,我会尽力将作业翻译成英文并使其尽可能准确:
我尝试使用如下所示的2个递归函数来实现:(赋值仅需要一个函数,因此这不是正确的答案)
public static int PDiv(int n1,int n2)
{
if (n1 < n2)
return 0;
else if (n1 == n2)
return 1;
else
return PDiv(n1,n2 + n2,n2) + 1;
}
public static int PDiv(int n1,int n2,int con)
{
if (n1 < n2)
return 0;
else if (n1 == n2)
return 1;
else
return PDiv(n1,con) + 1;
}
除此之外,我还尝试了一个确实有效的方法,但是它伪装成明智的做法,而不是真正地通过加法来实现,而是加上减法(基本上是减法)。示例:
public static int PDiv(int n1,int n2)
{
if (n1 < n2)
return 0;
else if (n1 == n2)
return 1;
else
return PDiv(n1 + -n2,n2) + 1;
}
如果有人对我的工作方式有所了解,我很想听听!预先感谢!
解决方法
如果可以使用取模运算符和局部变量,这是实现此目标的一种方法。
这个想法是,如果我们知道PDiv(n,m + m)
,我们只需要知道是否仍然可以再添加一个m
。
C#代码:
using System;
public class Test
{
public static int PDiv(int n,int m)
{
if (n < m)
return 0;
if (n == m)
return 1;
int k = PDiv(n,m + m);
return k + k + (n % (m + m) < m ? 0 : 1);
}
public static void Main()
{
Console.WriteLine(PDiv(21,3));
}
}
,
这是我们可以通过纯粹的加法,比较和赋值操作以及根据要求提供的两个参数来实现的方法,前提是允许我们提供元组返回值。 C#代码:
using System;
public class Test
{
// Returns (floor(n / m) * m,floor(n / m))
public static (int,int) f(int n,int m){
if (n < m)
return (0,0);
if (n == m)
return (n,1);
(int _n,int k) = f(n,m + m);
if (_n + m > n)
return (_n,k + k);
return (_n + m,k + k + 1);
}
public static void Main()
{
for (int n=1; n<200; n++){
for (int m=1; m<n; m++){
(int _n,int nm) = f(n,m);
if (nm != n / m)
Console.WriteLine($"Mismatch: { n },{ m }") ;
}
}
Console.WriteLine("Test done.");
}
}
,
您唯一的问题是,在使用n2 = n2 + con时,您仍然可以在第二种方法中将n1与n2进行比较,而con仍然盯着n2,它应该可以工作。
private int div(int n1,int n2)
{
if (n1 == n2) return 1;
if (n1 < n2) return 0;
return div(n1,n2,n2+n2) + 1;
}
private int div(int n1,int n2,int runner)
{
if (n1 == runner) return 1;
if (n1 < runner) return 0;
return div(n1,runner+n2) + 1;
}
,
d = a/b
d * b + r = a
第二行给出了如何以递归方式解决此问题的想法。
不考虑余数(r),将b加起来直到d*b > a
。这样,剩下要做的就是跟踪我们必须将b加在一起多少次,直到b大于a
。
int div_loop(int dividend,int divisor,int x,int n) {
if (x > dividend)
return (n-1);
return div_loop(dividend,divisor,(x + divisor),(n+1));
}
int div(int dividend,int divisor) {
return div_loop(dividend,0);
}
这应符合要求,因为要求不禁止编写辅助函数。而且main函数只有2个参数,这是一个递归解决方案,仅使用加法。
如果C#具有嵌套函数(不确定是否现在有,但是我上次用C#编程时没有),则div_loop()
可以嵌套在div()
函数内部,内部函数可以被视为实现细节(并减少了2个参数)。例如,在F#中,可能看起来像这样:
let div dividend divisor =
let rec operate x n =
if x > dividend
then (n - 1)
else operate (x + divisor) (n + 1)
operate 0 0
从Microsoft c# documentation开始,C#现在支持嵌套函数,其名称为“本地函数”。
因此,您可以满足所有要求,例如:
int pdiv(int dividend,int divisor) {
return div_loop(0,0);
int div_loop(int x,int n) {
if (x > dividend) return (n-1);
return div_loop(x+divisor,n + 1);
}
}