C# 使用PLINQ计算阶乘的递归函数

C# 使用PLINQ计算阶乘的递归函数,c#,recursion,parallel-processing,task-parallel-library,C#,Recursion,Parallel Processing,Task Parallel Library,注意我很清楚我在问什么,在正常情况下我不可能需要使用这样的函数,但它正被用作我正在进行的析因实验研究生项目的研究因子 我想使用PLINQ(而不是TPL)运行以下函数。我知道PLINQ在TPL上运行,但这是实验的一部分。此外,除非我不知道使用PLINQ的另一种方法,否则我相信我将不得不对阶乘方法进行一些“黑客”操作,以使用带有递归的for循环 因为并行类只提供For、ForEach和Invoke,它不提供我需要的东西,比如TPL做什么,我需要它返回,Invoke不这样做,所以对于每个递归调用,我必

注意我很清楚我在问什么,在正常情况下我不可能需要使用这样的函数,但它正被用作我正在进行的析因实验研究生项目的研究因子

我想使用PLINQ(而不是TPL)运行以下函数。我知道PLINQ在TPL上运行,但这是实验的一部分。此外,除非我不知道使用PLINQ的另一种方法,否则我相信我将不得不对阶乘方法进行一些“黑客”操作,以使用带有递归的for循环

因为并行类只提供For、ForEach和Invoke,它不提供我需要的东西,比如TPL做什么,我需要它返回,Invoke不这样做,所以对于每个递归调用,我必须使用For并从0,1开始执行For循环(是的,我知道它看起来很神奇)

我想做如下事情:

public ulong RecursivePLINQ(ulong factor)
    {
        if (factor > 1)
        {
            Parallel.For<ulong>(0, 1, () => factor, (j, loop, factorial) =>
            {
                Thread.Sleep(1);    /*Simulate Moderate Operation*/
                return factorial * RecursivePLINQ(--factorial);
            }, (i) => { });
        }


        return 1;

    }
public ulong recursiveplink(ulong因子)
{
如果(系数>1)
{
对于(0,1,()=>因子,(j,循环,因子)=>
{
线程。睡眠(1);/*模拟中等操作*/
返回阶乘*递归PLINQ(--阶乘);
},(i)=>{});
}
返回1;
}
目前,它似乎正在工作,但在最后一次调用中,它返回1,递归调用的结果是1,而不是递归更改的值。我似乎看不出哪里出了问题。我在这里展示了另一个TPL实现(同样用于研究),它正在工作

public ulong RecursiveTPL(ulong factor)
    {
        if (factor > 1)
        {
            Task<ulong> task = new Task<ulong>((f) =>
            {
                Thread.Sleep(1);    /*Simulate Moderate Operation*/
                ulong val = (ulong)f;
                return factor * RecursiveTPL(--val);
            }, factor);
            task.Start();
            task.Wait();
            return task.Result;
        }
            return 1;


    }
public ulong RecursiveTPL(ulong因子)
{
如果(系数>1)
{
任务=新任务((f)=>
{
线程。睡眠(1);/*模拟中等操作*/
ulong val=(ulong)f;
返回因子*RecursiveTPL(-val);
},因子);
task.Start();
task.Wait();
返回任务。结果;
}
返回1;
}
***请不要因为我的要求而解雇我,这是为了一个非常具体的研究目的******

编辑我在MSDN文档上看到了一个示例,其中显示了线程局部变量的使用,所以我尝试了类似的方法,但我的头开始有点眩晕……不要注意铸造,这只是为了看看我是否能让它工作

public ulong RecursivePLINQ(ulong factor)
    {
        long total = 0;
        if (factor > 1)
        {
            Parallel.For<ulong>(0, 1, () => factor, (j, loop, factorial) =>
            {
                Thread.Sleep(1);    /*Simulate Moderate Operation*/
                return factorial * RecursivePLINQ(--factorial);
            }, (i) =>  Interlocked.Add(ref total,(long)i)
            );
        }


        return (ulong)total;

    }
public ulong recursiveplink(ulong因子)
{
长总计=0;
如果(系数>1)
{
对于(0,1,()=>因子,(j,循环,因子)=>
{
线程。睡眠(1);/*模拟中等操作*/
返回阶乘*递归PLINQ(--阶乘);
},(i)=>联锁。添加(参考总计,(长)i)
);
}
返回(ulong)总数;
}

这并不漂亮,我真的不确定这对我来说是否有效,但它确实给出了正确的阶乘。我得到了这个解决方案,但我必须对总参数进行校正,以使其发挥作用,不确定我会称之为什么,或者是否有更好的方法,但现在必须这样做

public long RecursivePLINQ(long factor,long total)
    {

        if(total == 0)
        {
            total = 1;
        }
        if (factor > 1)
        {
            Parallel.For<long>(0, 1, () => factor, (j, loop, factorial) =>
            {
                Thread.Sleep(1);    /*Simulate Moderate Operation*/
                total = factorial * RecursivePLINQ(--factorial, total);
                return total;
            }, (i) =>  {return;});
        }
        return total;
    }
公共长递归PLINQ(长因子,长总计)
{
如果(总计==0)
{
总数=1;
}
如果(系数>1)
{
对于(0,1,()=>因子,(j,循环,因子)=>
{
线程。睡眠(1);/*模拟中等操作*/
总计=阶乘*递归PLINQ(--阶乘,总计);
返回总数;
},(i)=>{return;});
}
返回总数;
}
无耻地从复制,您可以使用聚合扩展方法计算阶乘:

int value=5; 
var factorial=Enumerable.Range(1, value).AsParallel()
             .Aggregate(1, (result, number)=>      
                           result*number, result=>result);
您可以认为聚合执行手动执行的递归,或者您可以编写递归调用自身以计算阶乘的代码

不过,和其他人一样,我看不出你会取得什么成就。您的代码将由PLINQ的设置和拆卸控制,您得到的任何数字都将毫无意义


如果有什么区别的话,PLINQ被用来用一系列可以并行执行的运算符来替换循环代码,而程序员不必指定如何执行

我猜行
返回任务。结果在这里很重要。是的,我相信是的,但我不知道如何在第一个函数中表示它。我也不知道。甚至使用
并行。For
?你知道,如果你启动几个线程,你会传播哪一个线程的结果?哈哈,这就是我发布这篇文章的原因,看看是否有办法使用Parallel.For或另一个PLINQ操作来破解这个函数:/n你可以通过写入传递的引用/闭合变量(如果C#有闭包)来返回它并不漂亮,而且它只是偶然地起作用。如果您的循环有多个迭代,它将不起作用。该循环只有一个有意的迭代。这是一个hack,因此我可以利用并行For,而无需迭代集合。正如我提到的,这是出于一个非常具体的原因。