Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#递归函数有助于理解它是如何工作的?_C#_Recursion_Yield Return - Fatal编程技术网

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