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

项目中需要快速求解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;

            }
        }
    }
时间: 2024-10-22 11:52:00

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

zoj 3625 D - Geek&#39;s Collection(正项无穷级数,麦克劳林展开式,2015年10月AC)

D - Geek's Collection Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Submit Status Description The word geek is a slang term, with different meanings ranging from "a computer expert or enthusiast" to "a carni

使用matplotlib模拟e^x的麦克劳林展开式

使用matplotlib模拟下e^x的麦克劳林展开式,用plt画图一开始觉得还是挺有意思的. import matplotlib.pyplot as plt import numpy as np import random ''' e^x的麦克劳林展开式: e^x= f(0)+ f′(0)x+ f″(0)x 2/ 2!+...+ f?(0)x^n/n!+Rn(x) =1+x+x^2/2!+x^3/3!+...+x^n/n!+Rn(x) ''' # 阶乘函数 def factorial(n): x

泰勒展开式

数学中,泰勒公式是一个用函数在某点的信息描述其附近取值的公式.如果函数足够平滑的话,在已知函数在某一点的各阶导数值的情况之下,泰勒公式可以用这些导数值做系数构建一个多项式来近似函数在这一点的邻域中的值.泰勒公式还给出了这个多项式和实际的函数值之间的偏差. 泰勒公式是将一个在x=x0处具有n阶导数的函数f(x)利用关于(x-x0)的n次多项式来逼近函数的方法. 若函数f(x)在包含x0的某个闭区间[a,b]上具有n阶导数,且在开区间(a,b)上具有(n+1)阶导数,则对闭区间[a,b]上任意一点x

等价无穷小、常用泰勒展开式

等价无穷小 可直接等价替换的类型: 变上限积分函数(积分变限函数)也可以用等价无穷小进行替换. 泰勒展开式的重要性体现在以下五个方面: 1.幂级数的求导和积分可以逐项进行,因此求和函数相对比较容易. 2.一个解析函数可e799bee5baa631333431343633被延伸为一个定义在复平面上的一个开片上的解析函数,并使得复分析这种手法可行. 3.泰勒级数可以用来近似计算函数的值,并估计误差. 4.证明不等式. 5.求待定式的极限. 常用泰勒展开公式如下: 1.e^x = 1+x+x^2/2!

使用泰勒展开式求sin(x)的近似值-C

具体定义参见百度 1 #include<stdio.h> 2 #include<math.h> 3 4 int main(void) 5 { 6 double x=3.455; 7 8 int index=1; 9 10 double s=x; 11 double n=x; 12 13 do 14 { 15 index+=2; 16 n=n * (-x*x)/((index)*(index-1)); 17 s+=n; 18 }while(fabs(n)>=1e-8); 19

c++ sin的泰勒展开式实现

// sinx.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> using std::cout; using std::cin; using std::endl; int factorial(int num){     int a=1;     for(int i=1;i<num;i++){         a=a*(i+1);     }     return a; } double s

XGBoost 完整推导过程

参考: 陈天奇-"XGBoost: A Scalable Tree Boosting System" Paper地址: <https://arxiv.org/abs/1603.02754 文哲大佬全程手推 兄弟们, 再来手撸一波XGBoost, 这上半月目标算达成了. 感觉比上次撸 SVM 还是要难一些的. 但必须手撸, 因为, 近两年, 我已认识到, 很多梦魇, 只有从源头上彻底消灭后, 便不会时常萦绕心灵... 一边看原paper 和贪心地搬运大佬的知识,化为己有, 其乐无穷

复旦考研信息整理

复旦大学考研网:http://www.kaofudan.com/kaoyanjingyan/ 复旦大学考研资料:http://yz.kaoyan.com/fudan/ziliao/ 复旦大学考研真题:http://download.kaoyan.com/list-12-t-1 复旦大学考研网:http://www.kaofudan.com/kaoyanziliao/ 计算机科学与技术专业:http://www.kaofudan.com/kaoyanziliao/jisuanjikexuejish

(一)泰勒级数展开

1 #coding=utf-8 2 from sympy import * 3 import math 4 5 #定义变量x 6 x=Symbol("x") 7 #定义函数f 8 f = -0.1*x**4-0.15*x**3-0.5*x**2-0.25*x+1.2 9 10 #求出一到四阶导为 11 d1 = diff(f,x,1) 12 d2 = diff(f,x,2) 13 d3 = diff(f,x,3) 14 d4 = diff(f,x,4) 15 print d1,d2,d