自己用C#写的一个Math类,数学不好,大家帮我看下

最近一直在用C#写程序,第一次使用C#,项目中有一个评估模块,涉及了一些算法,Math.Net应该都有,只是我不想去找到底用哪个,所以自己根据客户要求,写了一个类,算法公式由于客户提供的,我数学不好,不知道对不对,请大家帮我验证一下,谢谢!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace APSP.Common
{
    public static class MathTool
    {
        
        /// <summary>
        /// 获取相关系数
        /// 
        ///                ____________________
        ///               /   __
        ///              /    \   N   ╭     _         _ ╮
        ///             /      |     │(Cm - Cm)×(Co - Co) │
        ///            /      /   i=1╰                     ╯
        ///           /        ̄ ̄
        ///  R =     /    ――――――――――――――――――――
        ///         /     ____________________
        ///        /     /  __                __
        ///       /     /   \   N        _     \   N        _
        ///      /     /     |     (Cm - Cm)²×  |     (Co - Co)² 
        ///     /     /     /   i=1             /   i=1  
        ///   √    √       ̄ ̄                 ̄ ̄     
        ///   
        ///         Cm:模拟值
        ///         Co:观测值
        ///         N :样本个数
        /// </summary>
        /// <param name="Cm">模拟值</param>
        /// <param name="Co">观测值</param>
        /// <returns>相关系数R</returns>
        public static double Correlation(IEnumerable<double> Cm, IEnumerable<double> Co)
        {
            double R = 0.0;
            double CmAvr = 0.0;
            double CoAvr = 0.0;

            double CmCoAvrDifProSum = 0.0;     //模拟值与平均模拟值的差 和 观测值与平均观测值的差 的乘积和
            double CmAvrDifSqSum = 0.0;     //模拟值与平均模拟值的差的平方和
            double CoAvrDifSqSum = 0.0;     //观测值与平均观测值的差的平方和

            int n = 0;

            CmAvr = Average(Cm);
            CoAvr = Average(Co);

            using (IEnumerator<double> CmArr = Cm.GetEnumerator())
            using (IEnumerator<double> CoArr = Co.GetEnumerator())
            {
                while (CmArr.MoveNext())
                {
                    if (!CoArr.MoveNext())
                    {
                        throw new ArgumentOutOfRangeException("Correlation", "dataB is not consistent with dataA length");
                    }

                    double currCm = CmArr.Current;
                    double currCo= CoArr.Current;

                    double CmAvrDif = currCm - CmAvr;   //模拟值与平均模拟值的差
                    double CoAvrDif = currCo - CoAvr;   //观测值与平均观测值的差

                    double CmAvrDifSq = CmAvrDif * CmAvrDif;   //模拟值与平均模拟值的差的平方
                    double CoAvrDifSq = CoAvrDif * CoAvrDif;   //观测值与平均观测值的差的平方

                    CmCoAvrDifProSum += (CmAvrDif * CoAvrDif);  //模拟值与平均模拟值的差 和 观测值与平均观测值的差 的乘积和

                    CmAvrDifSqSum += CmAvrDifSq;        //模拟值与平均模拟值的差的平方和
                    CoAvrDifSqSum += CoAvrDifSq;        //观测值与平均观测值的差的平方和
                    n++;

                }
            }
            
            R = Math.Sqrt(CmCoAvrDifProSum / Math.Sqrt(CmAvrDifSqSum * CoAvrDifSqSum ));

            return R;
        }
        /// <summary>
        /// 求数组内数据的平均值
        /// </summary>
        /// <param name="data">输入数组</param>
        /// <returns>平均值</returns>
        public static double Average(IEnumerable<double> data)
        {
            double varNum = 0.0;
            double sumNum = 0.0;
            int n = 0;
            using (IEnumerator<double> ie = data.GetEnumerator())
            {
                while (ie.MoveNext())
                {
                    double currentNum = ie.Current;
                    sumNum += currentNum;
                    n++;
                }
            }

            varNum = sumNum / n;
            return varNum;
        }
        /// <summary>
        /// 求两组数据的平均偏差
        ///              __
        ///          1   \   N         
        ///   MB =  ――  |     (Cm - Co)×100%
        ///          N   /   i=1                    
        ///               ̄ ̄
        ///         Cm:模拟值
        ///         Co:观测值
        ///         N :样本个数  
        /// </summary>
        /// <param name="Cm">模拟值</param>
        /// <param name="Co">观测值</param>
        /// <returns>平均偏差(MB)</returns>
        public static double GetMB(IEnumerable<double> Cm, IEnumerable<double> Co)
        {
            double MB = 0.0;
            double CmCoDifSum = 0.0;
            int n = 0;
            using (IEnumerator<double> CmArr = Cm.GetEnumerator())
            using (IEnumerator<double> CoArr = Co.GetEnumerator())
            {
                while (CmArr.MoveNext())
                {
                    if (!CoArr.MoveNext())
                    {
                        throw new ArgumentOutOfRangeException("GetMB", "dataB is not consistent with dataA length");
                    }

                    double currCm = CmArr.Current;
                    double currCo = CoArr.Current;

                    CmCoDifSum += (currCm - currCo);
                    n++;
                }
            }
            MB = CmCoDifSum / n;
            return MB;
        }
        /// <summary>
        /// 求两组数据的平均误差
        ///              __
        ///          1   \   N         
        ///   ME =  ――  |     |Cm - Co|×100%
        ///          N   /   i=1                    
        ///               ̄ ̄
        ///         Cm:模拟值
        ///         Co:观测值
        ///         N :样本个数  
        /// </summary>
        /// <param name="Cm">模拟值</param>
        /// <param name="Co">观测值</param>
        /// <returns>平均误差(ME)</returns>
        public static double GetME(IEnumerable<double> Cm, IEnumerable<double> Co)
        {
            double ME = 0.0;

            double CmCoDifAbsSum = 0.0;
            int n = 0;
            using (IEnumerator<double> CmArr = Cm.GetEnumerator())
            using (IEnumerator<double> CoArr = Co.GetEnumerator())
            {
                while (CmArr.MoveNext())
                {
                    if (!CoArr.MoveNext())
                    {
                        throw new ArgumentOutOfRangeException("GetME", "dataB is not consistent with dataA length");
                    }

                    double currCm = CmArr.Current;
                    double currCo = CoArr.Current;

                    CmCoDifAbsSum += Math.Abs(currCm - currCo);
                    n++;
                }
            }
            ME = CmCoDifAbsSum / n;
            return ME;
        }
        /// <summary>
        /// 求两组数据的相对偏差
        ///              __
        ///          2   \   N   (Cm - Co)       
        ///   FB =  ――  |      ――――― ×100%
        ///          N   /   i=1 (Cm + Co)                    
        ///               ̄ ̄
        ///         Cm:模拟值
        ///         Co:观测值
        ///         N :样本个数  
        /// </summary>
        /// <param name="Cm">模拟值</param>
        /// <param name="Co">观测值</param>
        /// <returns>相对偏差(FB)</returns>
        public static double GetFB(IEnumerable<double> Cm, IEnumerable<double> Co)
        {
            double FB = 0.0;
            double sumNum = 0.0;
            int n = 0;
            using (IEnumerator<double> CmArr = Cm.GetEnumerator())
            using (IEnumerator<double> CoArr = Co.GetEnumerator())
            {
                while (CmArr.MoveNext())
                {
                    if (!CoArr.MoveNext())
                    {
                        throw new ArgumentOutOfRangeException("GetFB", "dataB is not consistent with dataA length");
                    }

                    double currCm = CmArr.Current;
                    double currCo = CoArr.Current;

                    sumNum += ((currCm - currCo) / (currCm + currCo));

                    n++;
                }
            }
            FB = sumNum * 2 / n;

            return FB;

        }

        /// <summary>
        /// 求两组数据的相对偏差
        ///              __
        ///          2   \   N   |Cm - Co|       
        ///   FE =  ――  |      ――――― ×100%
        ///          N   /   i=1 (Cm + Co)                    
        ///               ̄ ̄
        ///         Cm:模拟值
        ///         Co:观测值
        ///         N :样本个数  
        /// </summary>
        /// <param name="Cm">模拟值</param>
        /// <param name="Co">观测值</param>
        /// <returns>相对偏差(FE)</returns>
        public static double GetFE(IEnumerable<double> Cm, IEnumerable<double> Co)
        {
            double FE = 0.0;
            double sumNum = 0.0;
            int n = 0;
            using (IEnumerator<double> CmArr = Cm.GetEnumerator())
            using (IEnumerator<double> CoArr = Co.GetEnumerator())
            {
                while (CmArr.MoveNext())
                {
                    if (!CoArr.MoveNext())
                    {
                        throw new ArgumentOutOfRangeException("GetFE", "dataB is not consistent with dataA length");
                    }

                    double currCm = CmArr.Current;
                    double currCo = CoArr.Current;

                    sumNum += (Math.Abs(currCm - currCo) / (currCm + currCo));

                    n++;
                }
            }
            FE = sumNum * 2 / n;

            return FE;

        }
        /// <summary>
        /// 求两组数据的平均标准偏差
        ///              __
        ///          1   \   N   ╭ Cm - Co ╮      
        ///   MNB = ――  |     │――――― │×100%
        ///          N   /   i=1╰    Co     ╯                
        ///               ̄ ̄
        ///         Cm:模拟值
        ///         Co:观测值
        ///         N :样本个数  
        /// </summary>
        /// <param name="Cm">模拟值</param>
        /// <param name="Co">观测值</param>
        /// <returns>平均标准偏差(MNB)</returns>
        public static double GetMNB(IEnumerable<double> Cm, IEnumerable<double> Co)
        {
            double MNB = 0.0;
            double sumNum = 0.0;
            int n = 0;

            using (IEnumerator<double> CmArr = Cm.GetEnumerator())
            using (IEnumerator<double> CoArr = Co.GetEnumerator())
            {
                while (CmArr.MoveNext())
                {
                    if (!CoArr.MoveNext())
                    {
                        throw new ArgumentOutOfRangeException("GetMNB", "dataB is not consistent with dataA length");
                    }

                    double currCm = CmArr.Current;
                    double currCo = CoArr.Current;

                    sumNum += ((currCm - currCo) / currCo);

                    n++;
                }
            }
            MNB = sumNum / n;
            return MNB;
        }
        /// <summary>
        /// 求两组数据的平均标准误差
        ///              __
        ///          1   \   N   |  Cm - Co |     
        ///   MNE = ――  |      |―――――| ×100%
        ///          N   /   i=1 |    Co    |                
        ///               ̄ ̄
        ///         Cm:模拟值
        ///         Co:观测值
        ///         N :样本个数  
        /// </summary>
        /// <param name="Cm">模拟值</param>
        /// <param name="Co">观测值</param>
        /// <returns>平均标准误差(MNE)</returns>
        public static double GetMNE(IEnumerable<double> Cm, IEnumerable<double> Co)
        {
            double MNE = 0.0;
            double sumNum = 0.0;
            int n = 0;
            using (IEnumerator<double> CmArr = Cm.GetEnumerator())
            using (IEnumerator<double> CoArr = Co.GetEnumerator())
            {
                while (CmArr.MoveNext())
                {
                    if (!CoArr.MoveNext())
                    {
                        throw new ArgumentOutOfRangeException("GetMNE", "dataB is not consistent with dataA length");
                    }

                    double currCm = CmArr.Current;
                    double currCo = CoArr.Current;

                    sumNum += Math.Abs((currCm - currCo) / currCo);

                    n++;
                }
            }

            MNE = sumNum / n;
            return MNE;
        }

        /// <summary>
        /// 求两组数据的标准平均偏差
        ///       __
        ///       \   N        
        ///        |      (Cm - Co) 
        ///       /   i=1             
        ///        ̄ ̄
        /// NMB = ――――――――― ×100%
        ///              __
        ///              \   N   
        ///               |      Co
        ///              /   i=1               
        ///               ̄ ̄
        ///         Cm:模拟值
        ///         Co:观测值
        ///         N :样本个数  
        /// </summary>
        /// <param name="Cm">模拟值</param>
        /// <param name="Co">观测值</param>
        /// <returns>标准平均偏差(NMB)</returns>
        public static double GetNMB(IEnumerable<double> Cm, IEnumerable<double> Co)
        {
            double NMB = 0.0;
            double CmCoDifSum = 0.0;
            double CoSum = 0.0;
            int n = 0;

            using (IEnumerator<double> CmArr = Cm.GetEnumerator())
            using (IEnumerator<double> CoArr = Co.GetEnumerator())
            {
                while (CmArr.MoveNext())
                {
                    if (!CoArr.MoveNext())
                    {
                        throw new ArgumentOutOfRangeException("GetNMB", "dataB is not consistent with dataA length");
                    }

                    double currCm = CmArr.Current;
                    double currCo = CoArr.Current;

                    CmCoDifSum += (currCm - currCo);
                    CoSum += currCo;
                    n++;
                }
            }
            NMB = CmCoDifSum / CoSum;
            return NMB;
        }
        /// <summary>
        /// 求两组数据的标准平均误差
        ///       __
        ///       \   N        
        ///        |      |Cm - Co|
        ///       /   i=1             
        ///        ̄ ̄
        /// NME = ――――――――― ×100%
        ///              __
        ///              \   N
        ///               |      Co
        ///              /   i=1
        ///               ̄ ̄
        ///         Cm:模拟值
        ///         Co:观测值
        ///         N :样本个数  
        /// </summary>
        /// <param name="Cm">模拟值</param>
        /// <param name="Co">观测值</param>
        /// <returns>标准平均误差(NME)</returns>
        public static double GetNME(IEnumerable<double> Cm, IEnumerable<double> Co)
        {
            double NME = 0.0;
            double CmCoDifSum = 0.0;
            double CoSum = 0.0;
            int n = 0;

            using (IEnumerator<double> CmArr = Cm.GetEnumerator())
            using (IEnumerator<double> CoArr = Co.GetEnumerator())
            {
                while (CmArr.MoveNext())
                {
                    if (!CoArr.MoveNext())
                    {
                        throw new ArgumentOutOfRangeException("GetNME", "dataB is not consistent with dataA length");
                    }

                    double currCm = CmArr.Current;
                    double currCo = CoArr.Current;

                    CmCoDifSum += Math.Abs(currCm - currCo);
                    CoSum += currCo;
                    n++;
                }
            }
            NME = CmCoDifSum / CoSum;
            return NME;
        }
        /// <summary>
        /// 求两组数据的平均相对偏差
        /// 
        /// MFB = SUM((Cmi-Coi)/(Coi+Cmi/2))/N  [i = 1...N]
        ///              __
        ///          1   \   N     (Cm - Co)       
        ///  MFB =  ――  |      ―――――― ×100%
        ///          N   /   i=1  (Co + Cm/2)                    
        ///               ̄ ̄
        ///         Cm:模拟值
        ///         Co:观测值
        ///         N :样本个数  
        /// </summary>
        /// <param name="Cm">模拟值</param>
        /// <param name="Co">观测值</param>
        /// <returns>平均相对偏差(MFB)</returns>
        public static double GetMFB(IEnumerable<double> Cm, IEnumerable<double> Co)
        {
            double MFB = 0.0;
            double sumNum = 0.0;
            int n = 0;
            using (IEnumerator<double> CmArr = Cm.GetEnumerator())
            using (IEnumerator<double> CoArr = Co.GetEnumerator())
            {
                while (CmArr.MoveNext())
                {
                    if (!CoArr.MoveNext())
                    {
                        throw new ArgumentOutOfRangeException("GetNME", "dataB is not consistent with dataA length");
                    }

                    double currCm = CmArr.Current;
                    double currCo = CoArr.Current;

                    sumNum += ((currCm - currCo) / (currCo + (currCm / 2)));
                    
                    n++;
                }
            }
            MFB = sumNum / n;
            return MFB;
        }
        /// <summary>
        /// 求两组数据的平均相对误差
        ///              __
        ///          1   \   N     |Cm - Co|       
        ///  MFE =  ――  |      ―――――― ×100%
        ///          N   /   i=1  (Co + Cm/2)                    
        ///               ̄ ̄
        ///         Cm:模拟值
        ///         Co:观测值
        ///         N :样本个数  
        /// </summary>
        /// <param name="Cm">模拟值</param>
        /// <param name="Co">观测值</param>
        /// <returns>平均相对误差(MFE)</returns>
        public static double GetMFE(IEnumerable<double> Cm, IEnumerable<double> Co)
        {
            double MFE = 0.0;
            double sumNum = 0.0;
            int n = 0;
            using (IEnumerator<double> CmArr = Cm.GetEnumerator())
            using (IEnumerator<double> CoArr = Co.GetEnumerator())
            {
                while (CmArr.MoveNext())
                {
                    if (!CoArr.MoveNext())
                    {
                        throw new ArgumentOutOfRangeException("GetNME", "dataB is not consistent with dataA length");
                    }

                    double currCm = CmArr.Current;
                    double currCo = CoArr.Current;

                    sumNum += (Math.Abs(currCm - currCo) / (currCo + (currCm / 2)));

                    n++;
                }
            }
            MFE = sumNum / n;
            return MFE;
        }
        /// <summary>
        /// 求两组数据的均方根误差
        ///                   ___________
        ///                  /   __
        ///                 /    \   N        
        ///                /      |     (Cm - Co)²
        ///               /      /   i=1                    
        ///              /        ̄ ̄
        ///  RMSE =     /    ―――――――――――   
        ///            /               N
        ///          √
        ///         Cm:模拟值
        ///         Co:观测值
        ///         N :样本个数           
        /// </summary>
        /// <param name="Cm">模拟值</param>
        /// <param name="Co">观测值</param>
        /// <returns>均方根误差(RMSE)</returns>
        public static double GetRMSE(IEnumerable<double> Cm, IEnumerable<double> Co)
        {
            double RMSE = 0.0;

            double sumNum = 0.0;
            int n = 0;
            using (IEnumerator<double> CmArr = Cm.GetEnumerator())
            using (IEnumerator<double> CoArr = Co.GetEnumerator())
            {
                while (CmArr.MoveNext())
                {
                    if (!CoArr.MoveNext())
                    {
                        throw new ArgumentOutOfRangeException("GetNME", "dataB is not consistent with dataA length");
                    }

                    double currCm = CmArr.Current;
                    double currCo = CoArr.Current;

                    sumNum += ((currCm - currCo) * (currCm - currCo));

                    n++;
                }
            }
            RMSE = Math.Sqrt(sumNum / n);
            return RMSE;
        }
    }
}


猜你喜欢

转载自blog.csdn.net/octdream/article/details/78382971