65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 中的数值编程入门

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.63/5 (26投票s)

2010 年 6 月 9 日

BSD

4分钟阅读

viewsIcon

71553

在 C# 中编写数值软件时,你需要了解的一些首要事项。

引言

当你第一次用一种新的编程语言编写数值软件时,你会问以下问题:

  • 如何导入标准的数学库?
  • 如何使用常见的数学函数?
  • 包含了哪些数学函数,哪些需要我自己编写或从别处寻找?

例如,在 C 语言中,在调用任何数学函数之前,你需要添加 #include "math.h"。然后,你可以通过其传统名称调用函数。例如,要查找数字 x 的正弦值,只需调用 sin(x)

在 Python 中,你需要在源文件的顶部添加 import math。数学函数通常与 C 语言中的名称相同,但它们是名为 math 的类的方法,而不是全局函数。Python 中可用的数学函数不如 C 语言多,但你可以使用 SciPy 来访问海量的数学函数。

在 C# 中你需要做什么?有什么陷阱吗?哪些可用,哪些不可用?

C# 数学函数

在 C# 中,数学函数是 System.Math 类中的静态方法。你不需要添加任何引用。你可能希望在文件的顶部添加 using System;,这样你每次需要调用方法时就可以只输入 Math 而不是 System.Math

System.Math 中的函数遵循 .NET 命名约定,因此以大写字母开头。否则,数学函数的名称通常与 C 语言中的相同。例如,C 语言中的函数 expcos 在 C# 中对应于 Math.ExpMath.Cos。但是,也有一些差异。下表比较了 C 和 C# 函数的名称。

C System.Math
acos Acos
asin Asin
atan Atan
ceil Ceiling
cos Cos
cosh Cosh
exp Exp
fabs Abs
floor Floor
fmod IEEERemainder
log Log
log10 Log10
pow Pow
sin Sin
sinh Sinh
sqrt Sqrt
tan Tan
tanh Tanh

请注意,在 C# 函数名只是 C 名称首字母大写这一模式中有三个例外:CeilingAbsIEEERemainder

C 数学库中的有几个函数是 double 类上的方法,而不是 System.Math 上的方法。double 类具有 IsNanIsFinite 方法,分别对应于 math.h 中的 isnanisfinite 方法。(Visual Studio 的 math.h 版本有一个 _isnan 函数,但没有对应于 isfinite 的函数。)

数值极限

C# 中的数值极限对于 C 和 C++ 程序员来说有一些出乎意料的地方。

在 C# 中,double.MaxValuedouble 的最大有限值,对应于 C 中的 DBL_MAX。但是,常量 double.MinValue 与 C 中的 DBL_MIN 不同。同样,常量 double.Epsilon 也不对应于 C 中的 DBL_EPSILON这可能是从 C 或相关语言转过来的程序员最大的陷阱

以下代码打印出 float.h 中的数值极限。

printf("DBL_MAX     = %g\n", DBL_MAX);
printf("DBL_MIN     = %g\n", DBL_MIN);
printf("DBL_EPSILON = %g\n", DBL_EPSILON);

输出如下

DBL_MAX     = 1.79769e+308
DBL_MIN     = 2.22507e-308
DBL_EPSILON = 2.22045e-016

(常量 DBL_MAXDBL_MINDBL_EPSILON 对应于 C++ 中 numeric_limits<double>maxminepsilon 方法的返回值。)

这是等效的 C# 代码。

Console.WriteLine("double.MaxValue = {0}", double.MaxValue);
Console.WriteLine("double.MinValue = {0}", double.MinValue);
Console.WriteLine("double.Epsilon  = {0}", double.Epsilon);

C# 代码的输出如下:

double.MaxValue = 1.79769313486232E+308
double.MinValue = -1.79769313486232E+308
double.Epsilon  = 4.94065645841247E-324

简而言之,C 和 C# 对于“最大值”的含义相同,但对于“最小值”和“epsilon”的含义却不同。

常量 DBL_MINdouble.MinValue 不同,因为它们在不同的范围内进行最小化。DBL_MIN 是已标准化 double 的最小**正**值,而 C# 中的 double.MinValuedouble 的最小(即最负)有限值。

C 常量 DBL_EPSILON 是最小的正双精度数 x,使得 1 + x 不等于 1。通常,双精度数有大约 15 位精度,因此 DBL_EPSILON 的数量级为 10-16。(有关更精确的描述,请参阅 浮点数结构。)

C# 没有对应 DBL_EPSILON 的常量。C# 中的常量 double.Epsilon 类似于 C 常量 DBL_MINdouble.Epsilondouble 的最小可能正值,包括**非标准化**值。DBL_MIN 是限制为**标准化**值的 double 的最小正值。

缺失的功能

C# 中的数学函数列表非常有限。一些缺失的功能可以轻松地得到补充。例如,System.Math 不包含反双曲函数 asinhacoshatanh。但这些可以通过以下恒等式计算:

  • asinh(x) = log(x + sqrt(x2 + 1))
  • acosh(x) = log(x + sqrt(x2 - 1))
  • atanh(x) = (log(1+x) - log(1-x))/2

然而,其他你可能期望的数学函数则不容易实现。例如,C# 没有误差函数 erf(x)。这个函数实现起来并不简单,尽管此链接提供了 独立的 C# erf 代码

结论

总结

  • 数学函数是 System.Math 类中的成员。
  • 函数名是传统名称的首字母大写,有少数例外。
  • double 的数值极限常量看起来与 C 语言的对应项相似,但实际上并不相同。
  • C# 不自带对高级数学函数(如误差函数)的支持。

相关的 CodeProject 文章

历史

  • 2010 年 6 月 7 日:初始版本。
© . All rights reserved.