Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/316.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#中pi到N的位数_C#_.net_Algorithm_Math_Loops - Fatal编程技术网

如何使用循环计算C#中pi到N的位数

如何使用循环计算C#中pi到N的位数,c#,.net,algorithm,math,loops,C#,.net,Algorithm,Math,Loops,我该如何计算圆周率,以C#为单位,精确到小数点后的某个位数 我希望能够将一个数字传递到一个方法中,并将PI计算返回到小数位数 public decimal CalculatePi(int places) { // magic return pi; } Console.WriteLine(CalculatePi(5)); // Would print 3.14159 Console.WriteLine(CalculatePi(10)); // Would print 3.141

我该如何计算圆周率,以C#为单位,精确到小数点后的某个位数

我希望能够将一个数字传递到一个方法中,并将PI计算返回到小数位数

public decimal CalculatePi(int places)
{
    // magic
    return pi;
}

Console.WriteLine(CalculatePi(5)); // Would print 3.14159

Console.WriteLine(CalculatePi(10)); // Would print 3.1415926535
等等

我不在乎节目的速度。我只是希望它尽可能简单易懂。提前谢谢你的帮助

Math.Round(Math.PI, places)

如果您需要更高的精度,则使用双精度数据类型会有困难,因为它支持某个最大精度(由Math.PI提供)。

如果您对本机数学库提供的位数感到满意,那么它就很简单;刚好四舍五入到所需的位数。如果您需要更多的数字(几十位、数百位或数千位),则需要一个一次吐出一个数字的插口算法。Jeremy Gibbons在我的博客上发表了一篇文章,在那里你可以找到Scheme、C、Python、Haskell、Perl等格式的代码(但不是C#,对不起)。

最简单的方法是在字符串常量中存储大量的数字pi。然后,每当您需要精度的
n
位数时,您只需首先从0到
n+2

取一个子串,假设您需要任意数量的pi位数,并且我们不希望受到任何浮点数精度的限制,让我们将Pi函数定义为字符串而不是任何数字类型

我在搜索这项技术时发现的最酷的算法之一是。它不需要浮点运算,而且主要是一种迭代方法。它确实需要一些内存来存储中间计算中的整数数组

无需花时间简化或清理代码,这里是算法的一个实现(请注意,结果不会添加小数点)

如果您打算将此代码用于除个人用途以外的任何用途,请务必引用算法和本网站

C#代码
publicstaticstringcalculatePI(整数位数)
{   
数字++;
uint[]x=新uint[位数*10/3+2];
uint[]r=新uint[位数*10/3+2];
uint[]pi=新的uint[位数];
对于(int j=0;j=0;i--)
{
pi[i]+=c;
c=pi[i]/10;
结果=(pi[i]%10).ToString()+结果;
}
返回结果;
}
更新
我终于开始着手修复35位数字后出现的“进位错误”。事实上,链接文档的第6页专门讨论了这里发生的事情。我已经测试了1000位的最终版本。

经过多次搜索,我发现了以下小片段:

public static class BigMath
{
    // digits = number of digits to calculate;
    // iterations = accuracy (higher the number the more accurate it will be and the longer it will take.)
    public static BigInteger GetPi(int digits, int iterations)
    {
        return 16 * ArcTan1OverX(5, digits).ElementAt(iterations)
            - 4 * ArcTan1OverX(239, digits).ElementAt(iterations);
    }

    //arctan(x) = x - x^3/3 + x^5/5 - x^7/7 + x^9/9 - ...
    public static IEnumerable<BigInteger> ArcTan1OverX(int x, int digits)
    {
        var mag = BigInteger.Pow(10, digits);
        var sum = BigInteger.Zero;
        bool sign = true;
        for (int i = 1; true; i += 2)
        {
            var cur = mag / (BigInteger.Pow(x, i) * i);
            if (sign)
            {
                sum += cur;
            }
            else
            {
                sum -= cur;
            }
            yield return sum;
            sign = !sign;
        }
    }
}
公共静态类BigMath
{
//位数=要计算的位数;
//迭代次数=精度(数值越高,精度越高,所需时间越长。)
公共静态BigInteger GetPi(整数位数,整数迭代)
{
返回16*ArcTan1OverX(5位)。元素(迭代次数)
-4*ArcTan1OverX(239位)。元素(迭代);
}
//arctan(x)=x-x^3/3+x^5/5-x^7/7+x^9/9-。。。
公共静态IEnumerable ArcTan1OverX(整数x,整数位数)
{
var mag=biginger.Pow(10位);
var sum=BigInteger.0;
布尔符号=真;
for(int i=1;true;i+=2)
{
var cur=mag/(BigInteger.Pow(x,i)*i);
如果(签名)
{
sum+=cur;
}
其他的
{
sum-=cur;
}
收益率和收益率;
符号=!符号;
}
}
}

到目前为止,它正在发挥魅力。您只需从GAC添加System.Numerics库即可解析BigInteger类型。

与nicholas的算法相同,但使用收益率进行延迟计算

    static public IEnumerable<uint> Pi()
    {
        uint[] x = new uint[short.MaxValue];
        uint[] r = new uint[short.MaxValue];

        for (int j = 0; j < short.MaxValue; j++)
            x[j] = 20;

        for (int i = 0; i < short.MaxValue; i++)
        {
            uint carry = 0;
            for (int j = 0; j < x.Length; j++)
            {
                uint num = (uint)(x.Length - j - 1);
                uint dem = num * 2 + 1;

                x[j] += carry;

                uint q = x[j] / dem;
                r[j] = x[j] % dem;

                carry = q * num;
            }

            yield return (x[x.Length - 1] / 10);

            r[x.Length - 1] = x[x.Length - 1] % 10; ;
            for (int j = 0; j < x.Length; j++)
            {
                x[j] = r[j] * 10;
            }                    
        }
    }

在编程或数学方面很容易理解?看看这里:有一些示例方法可以将pi计算到20位,但是讨论了一些限制,例如缺乏精确性是的,您确实回答了问题,但这不是提问者想要的;-)。这只允许我去15位。小数点总是有4位小数?你从哪里得到这个想法的?@AlexFord:那么你需要更好地定义你的问题的领域。这个方法适用于你给出的两个例子(5和10 d.p.)。你的最大小数位数是多少?@usr:是的,我知道小数的含义,但你的评论仍然是胡说八道。如果我这样做:
decimalmypi=(decimal)Math.Round(Math.PI,10)我得到3.1415926536。换句话说,十进制类型中的10位小数。继续检查MSDN(),如果您不使用
IEnumerable
ElementAt
,而只提供
ArcTan1OverX
要进行的迭代次数,这会更快。@Dani,快多少?@Dani将您的优化应用于Chev的代码片段,创建一个新的答案。@Levitikon,我已经有一段时间没有看这个了,在一个不同的答案被接受后,我就停止了工作。我会在本周的某个时候回顾它,看看我是否能找到哪里出了问题。@fubo-四年后,你终于激励我去修复它了it@Levitikon,大约3年前,你问它是否有任何更新。。。我终于修好了很好,我用100k di测试了它
    static public IEnumerable<uint> Pi()
    {
        uint[] x = new uint[short.MaxValue];
        uint[] r = new uint[short.MaxValue];

        for (int j = 0; j < short.MaxValue; j++)
            x[j] = 20;

        for (int i = 0; i < short.MaxValue; i++)
        {
            uint carry = 0;
            for (int j = 0; j < x.Length; j++)
            {
                uint num = (uint)(x.Length - j - 1);
                uint dem = num * 2 + 1;

                x[j] += carry;

                uint q = x[j] / dem;
                r[j] = x[j] % dem;

                carry = q * num;
            }

            yield return (x[x.Length - 1] / 10);

            r[x.Length - 1] = x[x.Length - 1] % 10; ;
            for (int j = 0; j < x.Length; j++)
            {
                x[j] = r[j] * 10;
            }                    
        }
    }
 class Program
{
    static void Main(string[] args)
    {
        foreach (uint digit in Calculator.Pi().Take(100))
        {
            Console.WriteLine(digit);
        }

        Console.Read();
    }
}