码迷,mamicode.com
首页 > 其他好文 > 详细

实现 Math.Asin 迈克劳林(泰勒)展开式,结果比Math.Asin 慢一倍

时间:2014-10-10 11:17:04      阅读:267      评论:0      收藏:0      [点我收藏+]

标签:blog   http   io   os   ar   for   sp   div   on   

项目中需要快速求解Asin(x) 的近似值,原以为用泰勒展开式会快一些,结果比原生的慢一倍。

Math.ASin
        Time Elapsed:   9ms
        Gen 0:          0
        Gen 1:          0
        Gen 2:          0
Maclaurin.ASin
        Time Elapsed:   17ms
        Gen 0:          4
        Gen 1:          0
        Gen 2:          0

各位,谁有能力改进?

附:

http://www.mathportal.org/formulas/pdf/taylor-series-formulas.pdf

http://pages.pacificcoast.net/~cazelais/260/maclaurin.pdf

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using Diagnostics;

namespace Asin
{
    class Program
    {
        static void Main(string[] args)
        {
            int count = 100000;
            List<double> values = new List<double>(count);

            Random r = new Random();
            for (var i = 0; i <= count; ++i)
            {
                values .Add(r.NextDouble() * 2 - 1);
            }


            CodeTime.Init();
            int? iter = 0;
            CodeTime.Timer("Math.ASin", count, () =>
            {
                var i = iter.Value + 1;
                iter = i;

                Math.Asin(values[i]);

            });

            iter = 0;
            CodeTime.Timer("Maclaurin.ASin", count, () =>
            {
                var i = iter.Value + 1;
                iter = i;

                Maclaurin.Asin(values[i],3);

            });

            while (true)
            {
                iter = 0;
                CodeTime.Timer("Math.ASin", count, () =>
                {
                    var i = iter.Value + 1;
                    iter = i;

                    Math.Asin(values[i]);

                });

                iter = 0;
                CodeTime.Timer("Maclaurin.ASin", count, () =>
                {
                    var i = iter.Value + 1;
                    iter = i;

                    Maclaurin.Asin(values[i], 3);

                });
            }
           

            //var ret = Maclaurin.Asin(0.5, 3);
            //var ret2 = Math.Asin(0.5);
            //Console.WriteLine(ret);
            //Console.WriteLine(ret2);
            Console.ReadLine();
        }
    }

    class Maclaurin
    {
        class ASinImpl
        {
            private List<double> quotieties = new List<double>();
            private IEnumerator<double> computeQuotieties = null;

            public ASinImpl()
            {
                this.computeQuotieties = ComputeQuotiety();
            }

            public double Calc(double v, int precision = 2)
            {
                if (quotieties.Count < precision)
                {
                    for (var i = quotieties.Count; i < precision; ++i)
                    {
                        computeQuotieties.MoveNext();
                        quotieties.Add(computeQuotieties.Current);
                    }
                }

                double ret = 0;
                var values = ComputeValues(v);
                for (int i = 0; i < precision; ++i)
                {
                    values.MoveNext();
                    ret += quotieties[i]*values.Current;
                }

                return ret;
            }

            private IEnumerator<double> ComputeValues(double v)
            {
                double ret = 1;
                double q = v*v;
                for(int i = 0;;++i)
                {
                   
                    if (i == 0)
                    {
                        ret = v;
                        yield return ret;
                    }
                    else
                    {
                        ret *= q;
                        yield return ret;
                    }
                }

                throw new NotImplementedException();
            }

            private IEnumerator<double> ComputeQuotiety()
            {
                for (int i = 0;; i++)
                {
                   
                    double up = Factorial(2*i);

                    double down = Math.Pow(Math.Pow(2, i)*Factorial(i), 2)*(2*i + 1);

                    double quotiety = up/down;

                    yield return quotiety;


                }

                throw new NotImplementedException();
            }

            private long Factorial(long v )
            { 
                if( v < 0)
                    throw new ArgumentOutOfRangeException("v");

                if (v == 0)
                    return 1;

                if (v == 1)
                    return 1;

                long ret = 1;
                for (int i = 2; i <= v; ++i)
                {
                    ret *= i;
                }

                return ret;
            }
        }


        private static ASinImpl asinImpl = new ASinImpl();

        /// <summary>
        /// 
        /// </summary>
        /// <param name="v"></param>
        /// <param name="precision"></param>
        /// <returns></returns>
        public static double Asin(double v, int precision)
        {
            if (v < -1 || v > 1)
            {
                throw new ArgumentOutOfRangeException("v");
            }

            return asinImpl.Calc(v, precision);
        }
    }
}

 

通过一下优化:基本持平

    class ASinImpl
    {
        private readonly int _precision;
        private double[] _quotieties = null;
        private long[] _factorials =null;
        public ASinImpl(int precision = 3)
        {
            _precision = precision;
            _quotieties = new double[precision + 1];
            _factorials = new long[precision*2 + 1];
            Factorial(precision);
            ComputeQuotiety(precision);
        }

        public double Calc(double v)
        {
           
            double retVal = 0;

            double vVal = 1;
            double q = v * v;
            for (int i = 0; i < _precision; ++i)
            {

                if (i == 0)
                {
                    vVal = v;
                    //yield return ret;
                    retVal += _quotieties[i] * vVal;
                }
                else
                {
                    vVal *= q;
                    //yield return ret;
                    retVal += _quotieties[i] * vVal;
                }
            }

            return retVal;
        }


        private void ComputeQuotiety(int precision)
        {
            for (int i = 0; i <= precision ; i++)
            {
                
                double up = _factorials[2 * i];

                double down = Math.Pow(Math.Pow(2, i) * _factorials[i], 2) * (2 * i + 1);

                double quotiety = up / down;

                _quotieties[i] = quotiety;


            }

        }

        private void Factorial(int precision)
        {
            long ret = 1;
            for (long v = 0; v <= precision; ++v)
            {
                if (v == 0)
                    this._factorials[v] = 1;

                if (v == 1)
                    this._factorials[v] = 1;


                ret *= v;

                this._factorials[v] = ret;
                

            }
        }
    }

 

实现 Math.Asin 迈克劳林(泰勒)展开式,结果比Math.Asin 慢一倍

标签:blog   http   io   os   ar   for   sp   div   on   

原文地址:http://www.cnblogs.com/evlon/p/Asin.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!