我想使用此公式= ∑((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划分为2
或5
进行降低所需的位。如果做得正确,这也将大大提高速度。
但最终您的公式仍然需要永远融合到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)
因此,我只是将c
与x
中的第一次签名。当心每个平方都可以使所需的分数位宽度增加一倍...这就是截断的原因(它降低了准确性的蝙蝠可以提高性能要大得多)
您可以看到这种方法非常好,因为它不需要任何划分...只有位操作和乘法。
在这里比较:
[e]
reference 2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274
my e 2.7182818284590452353602874713526624977572470936999595749669676277240766303535475945713821785251664274
00000200 method 0: 2.7182818280709941626033162692782994930797533824790948079298224728031965377356362865659816488677135209
reference
是e
的首个100位数字。my e
是由此代码产生的,method 0
是由您的方程式在200个任意精度后的方程式产生的,最后零截断和%2,%5
优化以加快速度。
我的方法只花了几毫秒,而您的~20
秒才能达到这一点...
在这里直接在decadic基础上计算出相同的字符串:
- 计算欧拉的数字给出了有限数量的小数