https://zhuanlan.zhihu.com/p/12783824787
以下4个为商业库,性能都不错,发布的dll文件均未加密,容易逆向。(等我以后有空了,再来详细对比一下4个商业库的性能)
- ALGLIB(C++/C#/Java numerical analysis library): 有免费版和商业版,支持C++/C#/Java/Delphi/CPython五种语言,涵盖数据分析(分类与回归、统计学)、优化与非线性问题求解、插值与最小二乘拟合、线性代数、FFT等领域。免费版是开源的,官网下载的压缩包中就包含源代码,相对商业版缺少多线程、native HPC Kernels和Intel MKL,不想花钱的首选ALGLIB免费版;
- ILNumerics(ILNumerics – Technical Computing): 只有收费版,支持多核并行计算,绘图功能比较强大,涵盖线性代数、FFT等领域,支持HDF5文件;
- Dew.Math(Math Library Component Delphi Component C++ Builder Component Net): 只有收费版,涵盖矩阵和向量运算、DSP、统计学、数据挖掘、FFT等领域,利用AVX, AVX2, AVX512以及多核心加速。
- Extreme.Numerics(Build financial, engineering and scientific applications faster): 只有收费版,涵盖统计学、概率论、回归、机器学习、线性、代数、矩阵、向量、求解、优化、曲线拟合、fft、积分、微分、插值等领域。
以下均为开源库,性能方面大多不如商业库,
- SdcbArithmetic(https://github.com/sdcb/Sdcb.Arithmetic): 开源,作者的知乎账号是
@周杰,P/Invoke调用GMP(GNU Multiple Precision Arithmetic Library)和MPFR(multiple-precision floating-point computations)库,性能不错,可以进行高精度计算。
- MathNET Numerics(GitHub - mathnet/mathnet-numerics): 开源,知名度比较高,但项目更新频率低,性能很差,bug很多(下面有几个具体的例子),只能做做玩具级的应用,或者学生写作业用。
- AngouriMath(GitHub asc-community/AngouriMath): 符号运算库,可以解方程(组),求符号导数,解决集合问题等。
- CSharpMath(GitHub - verybadcat/CSharpMath): 根据Latex表达式渲染公式和符号。
- StringMath(GitHub - miroiu/string-math): 对字符串形式的数学表达式求值,比如double result = "1 * (2 - 3) ^ 2".Eval(); // 1.
- ncalc(GitHub - ncalc/ncalc): 对字符串形式的数学表达式求值。
- DecimalMath(GitHub - nathanpjones/DecimalMath): 包含Decimal版的Sqrt, Pow, Exp, Log, in, Cos, Tan, ASin, ACos, ATan, ATan2. 性能很差(下面有例子)。
以下为停止维护的开源库。
- MetaNumerics: github仓库最后一次commit的时间是2020-08-22,基本等于停止维护;
- AForgeNET: github仓库最后一次commit的时间是2020-06-19,基本等于停止维护;
- AccordNET: github仓库已于2020-11-19转为archived状态,不再更新;
这里推荐一下本人的另一篇博客:C#数学相关开发性能优化方法
免费版ALGLIB 4.04.0的源代码中,diffequations.cs文件的第571~605行,用除法定义浮点常数时加了大量的(double)进行强制类型转换,显得十分繁琐和丑陋,不知为何要这么写,而不是写成1.0 / 5.0, 3.0 / 10.0等。
// Cask-Karp solver
// Prepare coefficients table.
// Check it for errors
//
state.rka = new double[6];
state.rka[0] = 0;
state.rka[1] = (double)1/(double)5;
state.rka[2] = (double)3/(double)10;
state.rka[3] = (double)3/(double)5;
state.rka[4] = 1;
state.rka[5] = (double)7/(double)8;
state.rkb = new double[6, 5];
state.rkb[1,0] = (double)1/(double)5;
state.rkb[2,0] = (double)3/(double)40;
state.rkb[2,1] = (double)9/(double)40;
state.rkb[3,0] = (double)3/(double)10;
state.rkb[3,1] = -((double)9/(double)10);
state.rkb[3,2] = (double)6/(double)5;
state.rkb[4,0] = -((double)11/(double)54);
state.rkb[4,1]