带有任务的欧拉号



我想使用此公式= ∑((3K)计算多个线程的Euler号码 ^ 2 1)/(3K)!,k = 0,...,∞,但是到目前为止,我还没有得到正确的结果,一个问题是,当我使用相当大的数字时,我将出现在小数点范围内的阶乘功能的范围,这就是我到目前为止完成了

static void Main(string[] args)
{
   Console.WriteLine(Program.Calculate(5, 1));
}
public static decimal Calculate(int x, byte taskNumber)
{
   var tasks = new List<Task<decimal>>();
   for (int i = 0; i < x; i += (x / taskNumber))
   {
        int step = i;
        tasks.Add(Task.Run(() =>
        {
            int right = (step + x / taskNumber) > x ? x : (step + x / taskNumber);
            return ChunkE(step + 1, right);
        }));
    }
    Task.WaitAll(tasks.ToArray());
    return tasks.Select(t => t.Result).Aggregate(((i, next) => i + next));
    }

然后我有简单的阶乘和欧拉函数

public static decimal ChunkFactorial(int left, int right)
{
    //Console.WriteLine("ChunkFactorial Thread ID :" + Thread.CurrentThread.ManagedThreadId);
    if (left == right)
    {
        return left == 0 ? 1 : left;
    }
    else
    {
        return right * ChunkFactorial(left, right - 1);
    }
}
public static decimal ChunkE(int left, int right)
{
    if(left == right)
    {
        return left == 0 ? 1 : left;
    }
    else
    {
        return ((3 * right) * (3 * right) + 1) / ChunkFactorial(left, right) + ChunkE(left, right - 1);
    }
}

我要实现的目标是计算欧拉号,直到使用不同数量的任务进行x精确。

我接到的电话是41.01666..7,如果我增加了x小数,最终将溢出。我该如何解决我尝试使用biginteger的问题,但是然后开始变得混乱,我放松了结果的精度。

有什么想法?

同样,当我使用1个任务启动程序时,我会得到一个结果,当我以4(或1个不同1)启动程序时,我会得到不同的结果,我不知道我缺少什么。

如果允许您在实施之前转换术语,请考虑

(3k)^2/(3k)! = (3k)/(3k-1)! = 1/(3k-2)!+1/(3k-1)!

然后证明您的公式确实计算了Euler号码。

,但是您需要在(3K)中包括因子3!在阶乘计算中。

使用浮动点类型进行阶乘计算应该是完全可以的,因为在溢出发生之前应达到所需的精度。请注意,绑定的错误是下一个期限的两倍,而不是部分总和。

,由于这个问题的重点已经回答,所以我只是添加一些东西:

您可以对代码进行几次升级,例如每次计算阶乘时,您可以将Divident和Divider划分为25进行降低所需的位。如果做得正确,这也将大大提高速度。

但最终您的公式仍然需要永远融合到e!更不用说由于阶乘而引起的溢出。我正在使用更适合计算机的东西(不确定该公式从何处出来,尽管它很久以前)...

e = (1+1/x)^x

使用x -> +inf,使用数字的二进制表示时,这具有许多优势。我通过将2的幂用于x来完善该过程,这简化了很多事情...我的计算代码(基于我的arbnum类)就是这样:

    arbnum c,x;
    int bit=512;        // min(int_bits,fract_bits)/2 ... this is just remnant from fixed point code where bitwidth matters
    // e=(1+1/x)^x  ... x -> +inf
    c.one(); c>>=bit; c++;  // c = 1.000...0001b = (1+1/x)          = 2^-bits + 1
//  x.one(); x<<=bit;       // x = 1000...000.0b =    x   = 1/(c-1) = 2^+bits
        for (;bit;bit--)        // c = c^x = c^(2^bits) = e
            {
            c*=c;
            c._normalize(2048); // this just cut off the result to specific number of fractional bits only to speed up the computation instead you should cut of only last zeros !!!
            }

您可以看到,我从开始(bits)计算目标精度并截断结果(对于分数部分而言,可管理的位宽度)。如果您有固定点算术,那么您就不需要这样做(这只是我快速尝试将其从我的古老的固定点代码移植到我的新Arbnum类)。

因此,将位置设置为您想要的东西和截断尺寸。两者都应基于您的目标精度。如您所见,这不是迭代过程...循环中唯一的是power。它有点优化以了解它需要意识到您正在计算什么:

(1.000...0001b) ^ (1<<bits)

因此,我只是将cx中的第一次签名。当心每个平方都可以使所需的分数位宽度增加一倍...这就是截断的原因(它降低了准确性的蝙蝠可以提高性能要大得多)

您可以看到这种方法非常好,因为它不需要任何划分...只有位操作和乘法。

在这里比较:

[e]
reference          2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274
my e               2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274
00000200 method 0: 2.7182818280709941626033162692782994930797533824790948079298224728031965377356362865659816488677135209

referencee的首个100位数字。my e是由此代码产生的,method 0是由您的方程式在200个任意精度后的方程式产生的,最后零截断和%2,%5优化以加快速度。

我的方法只花了几毫秒,而您的~20秒才能达到这一点...

在这里直接在decadic基础上计算出相同的字符串:

  • 计算欧拉的数字给出了有限数量的小数

最新更新