c#递归函数有助于理解它是如何工作的?
我需要帮助了解函数是如何工作的;:这是一个具有收益率返回的递归函数,但我不知道它是如何工作的。它用于计算一组数据上的累积密度函数(近似值)。c#递归函数有助于理解它是如何工作的?,c#,recursion,yield-return,C#,Recursion,Yield Return,我需要帮助了解函数是如何工作的;:这是一个具有收益率返回的递归函数,但我不知道它是如何工作的。它用于计算一组数据上的累积密度函数(近似值)。 谢谢大家 /// Approximates the cumulative density through a recursive procedure /// estimating counts of regions at different resolutions. /// </summary> /// <param name="dat
谢谢大家
/// Approximates the cumulative density through a recursive procedure
/// estimating counts of regions at different resolutions.
/// </summary>
/// <param name="data">Source collection of integer values</param>
/// <param name="maximum">The largest integer in the resulting cdf (it has to be a power of 2...</param>
/// <returns>A list of counts, where entry i is the number of records less than i</returns>
public static IEnumerable<int> FUNCT(IEnumerable<int> data, int max)
{
if (max == 1)
{
yield return data.Count();
}
else
{
var t = data.Where(x => x < max / 2);
var f = data.Where(x => x > max / 2);
foreach (var value in FUNCT(t, max / 2))
yield return value;
var count = t.Count();
f = f.Select(x => x - max / 2);
foreach (var value in FUNCT(f, max / 2))
yield return value + count;
}
}
///通过递归过程近似累积密度
///估计不同分辨率下的区域计数。
///
///整数值的源集合
///结果cdf中的最大整数(它必须是2的幂。。。
///计数列表,其中条目i是小于i的记录数
公共静态IEnumerable函数(IEnumerable数据,int max)
{
如果(最大==1)
{
收益率返回数据。Count();
}
其他的
{
var t=数据,其中(x=>xx>max/2);
foreach(函数中的var值(t,max/2))
收益回报值;
var count=t.count();
f=f.Select(x=>x-max/2);
foreach(函数中的var值(f,max/2))
收益率返回值+计数;
}
}
一个有趣的问题。假设您了解函数的工作原理,那么函数的注释(在您的问题中)会非常有用。我对代码的注释可能会有所帮助:
public static IEnumerable<int> FUNCT(IEnumerable<int> data, int max)
{
if (max == 1)
{
// Effectively the end of the recursion.
yield return data.Count();
}
else
{
// Split the data into two sets
var t = data.Where(x => x < max / 2);
var f = data.Where(x => x > max / 2);
// In the set of smaller numbers, recurse to split it again
foreach (var value in FUNCT(t, max / 2))
yield return value;
// For the set of smaller numbers, get the count.
var count = t.Count();
// Shift the larger numbers so they are in the smaller half.
// This allows the recursive function to reach an end.
f = f.Select(x => x - max / 2);
// Recurse but add the count of smaller numbers. We already know there
// are at least 'count' values which are less than max / 2.
// Recurse to find out how many more there are.
foreach (var value in FUNCT(f, max / 2))
yield return value + count;
}
}
公共静态IEnumerable函数(IEnumerable数据,int max)
{
如果(最大==1)
{
//实际上是递归的结束。
收益率返回数据。Count();
}
其他的
{
//将数据分成两组
var t=数据,其中(x=>xx>max/2);
//在较小的数字集合中,递归以再次拆分它
foreach(函数中的var值(t,max/2))
收益回报值;
//对于较小的数字集,获取计数。
var count=t.count();
//移动较大的数字,使其位于较小的一半。
//这允许递归函数到达终点。
f=f.Select(x=>x-max/2);
//递归,但是加上较小的数。我们已经知道了
//至少是小于最大值/2的“计数”值。
//递归以找出还有多少。
foreach(函数中的var值(f,max/2))
收益率返回值+计数;
}
}
一个有趣的问题。假设您了解函数的工作原理,那么函数的注释(在您的问题中)会非常有用。我对代码的注释可能会有所帮助:
public static IEnumerable<int> FUNCT(IEnumerable<int> data, int max)
{
if (max == 1)
{
// Effectively the end of the recursion.
yield return data.Count();
}
else
{
// Split the data into two sets
var t = data.Where(x => x < max / 2);
var f = data.Where(x => x > max / 2);
// In the set of smaller numbers, recurse to split it again
foreach (var value in FUNCT(t, max / 2))
yield return value;
// For the set of smaller numbers, get the count.
var count = t.Count();
// Shift the larger numbers so they are in the smaller half.
// This allows the recursive function to reach an end.
f = f.Select(x => x - max / 2);
// Recurse but add the count of smaller numbers. We already know there
// are at least 'count' values which are less than max / 2.
// Recurse to find out how many more there are.
foreach (var value in FUNCT(f, max / 2))
yield return value + count;
}
}
公共静态IEnumerable函数(IEnumerable数据,int max)
{
如果(最大==1)
{
//实际上是递归的结束。
收益率返回数据。Count();
}
其他的
{
//将数据分成两组
var t=数据,其中(x=>xx>max/2);
//在较小的数字集合中,递归以再次拆分它
foreach(函数中的var值(t,max/2))
收益回报值;
//对于较小的数字集,获取计数。
var count=t.count();
//移动较大的数字,使其位于较小的一半。
//这允许递归函数到达终点。
f=f.Select(x=>x-max/2);
//递归,但是加上较小的数。我们已经知道了
//至少是小于最大值/2的“计数”值。
//递归以找出还有多少。
foreach(函数中的var值(f,max/2))
收益率返回值+计数;
}
}
本质上,IEnumerable函数使用的收益返回函数与传统递归函数略有不同。作为基本情况,假设您有:
IEnumerable<int> F(int n)
{
if (n == 1)
{
yield return 1;
yield return 2;
// implied yield return break;
}
// Enter loop 1
foreach (var v in F(n - 1))
yield return v;
// End loop 1
int sum = 5;
// Enter loop 2
foreach (var v in F(n - 1))
yield return v + sum;
// End loop 2
// implied yield return break;
}
void Main()
{
foreach (var v in F(2))
Console.Write(v);
// implied return
}
并打印1267
。请注意,yield return
语句将控制权交给调用者,但下一次迭代会使函数继续它以前产生的位置
CDF方法确实增加了一些额外的复杂性,但不会增加太多。递归将集合分成两部分,并计算每个部分的CDF,直到max=1。然后函数计算元素的数量并生成它,每个生成递归地传播到封闭循环中
要浏览FUNCT
,假设您使用data=[0,1,0,1,2,3,2,1]
和max=4
运行function。然后使用与上面相同的Main
函数作为驱动程序运行该方法,得到:
FUNCT([0,1,0,1,2,3,2,1], 4)
| max/2 = 2
| t = [0,1,0,1,1]
| f = [3] // (note: per my comment to the original question,
| // should be [2,3,2] to get true CDF. The 2s are
| // ignored since the method uses > max/2 rather than
| // >= max/2.)
| FUNCT(t,max/2) = FUNCT([0,1,0,1,1], 2)
| | max/2 = 1
| | t = [0,0]
| | f = [] // or [1,1,1]
| | FUNCT(t, max/2) = FUNCT([0,0], 1)
| | | max = 1
| | | yield return data.count = [0,0].count = 2
| | yield return 2
| yield return 2
Console.Write(2)
| | | RETURNS
| | count = t.count = 2
| | F(f, max/2) = FUNCT([], 1)
| | | max = 1
| | | yield return data.count = [].count = 0
| | yield return 0 + count = 2
| yield return 2
Console.Write(2)
| | | RETURNS
| | RETURNS
| count = t.Count() = 5
| f = f - max/2 = f - 2 = [1]
| FUNCT(f, max/2) = FUNCT([1], 2)
| | max = 2
| | max/2 = 1
| | t = []
| | f = [] // or [1]
| | FUNCT(t, max/2) = funct([], 1)
| | | max = 1
| | | yield return data.count = [].count = 0
| | yield return 0
| yield return 0 + count = 5
Console.Write(5)
| | | RETURNS
| | count = t.count = [].count = 0
| | f = f - max/2 = []
| | F(f, max/2) = funct([], 1)
| | | max = 1
| | | yield return data.count = [].count = 0
| | yield return 0 + count = 0 + 0 = 0
| yield return 0 + count = 0 + 5 = 5
Console.Write(5)
| | RETURNS
| RETURNS
RETURNS
因此,这将返回值(2,2,5,5)。(使用=
将产生值(2,5,7,8)--请注意,这些是非负积分数据的缩放CDF的精确值,而不是近似值).本质上,IEnumerable函数使用的收益返回函数与传统递归函数略有不同。作为基本情况,假设您有:
IEnumerable<int> F(int n)
{
if (n == 1)
{
yield return 1;
yield return 2;
// implied yield return break;
}
// Enter loop 1
foreach (var v in F(n - 1))
yield return v;
// End loop 1
int sum = 5;
// Enter loop 2
foreach (var v in F(n - 1))
yield return v + sum;
// End loop 2
// implied yield return break;
}
void Main()
{
foreach (var v in F(2))
Console.Write(v);
// implied return
}
并打印1267
。请注意,yield return
语句将控制权交给调用者,但下一次迭代会使函数继续它以前产生的位置
CDF方法确实增加了一些额外的复杂性,但不会增加太多。递归将集合分成两部分,并计算每个部分的CDF,直到max=1。然后函数计算元素的数量并生成它,每个生成递归地传播到封闭循环中
要浏览FUNCT
,假设您使用data=[0,1,0,1,2,3,2,1]
和max=4
运行function。然后使用与上面相同的Main
函数作为驱动程序运行该方法,得到:
FUNCT([0,1,0,1,2,3,2,1], 4)
| max/2 = 2
| t = [0,1,0,1,1]
| f = [3] // (note: per my comment to the original question,
| // should be [2,3,2] to get true CDF. The 2s are
| // ignored since the method uses > max/2 rather than
| // >= max/2.)
| FUNCT(t,max/2) = FUNCT([0,1,0,1,1], 2)
| | max/2 = 1
| | t = [0,0]
| | f = [] // or [1,1,1]
| | FUNCT(t, max/2) = FUNCT([0,0], 1)
| | | max = 1
| | | yield return data.count = [0,0].count = 2
| | yield return 2
| yield return 2
Console.Write(2)
| | | RETURNS
| | count = t.count = 2
| | F(f, max/2) = FUNCT([], 1)
| | | max = 1
| | | yield return data.count = [].count = 0
| | yield return 0 + count = 2
| yield return 2
Console.Write(2)
| | | RETURNS
| | RETURNS
| count = t.Count() = 5
| f = f - max/2 = f - 2 = [1]
| FUNCT(f, max/2) = FUNCT([1], 2)
| | max = 2
| | max/2 = 1
| | t = []
| | f = [] // or [1]
| | FUNCT(t, max/2) = funct([], 1)
| | | max = 1
| | | yield return data.count = [].count = 0
| | yield return 0
| yield return 0 + count = 5
Console.Write(5)
| | | RETURNS
| | count = t.count = [].count = 0
| | f = f - max/2 = []
| | F(f, max/2) = funct([], 1)
| | | max = 1
| | | yield return data.count = [].count = 0
| | yield return 0 + count = 0 + 0 = 0
| yield return 0 + count = 0 + 5 = 5
Console.Write(5)
| | RETURNS
| RETURNS
RETURNS
这将返回值(2,2,5