C# 中的数值编程入门






4.63/5 (26投票s)
在 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 语言中的函数 exp
和 cos
在 C# 中对应于 Math.Exp
和 Math.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 名称首字母大写这一模式中有三个例外:Ceiling
、Abs
和 IEEERemainder
。
C 数学库中的有几个函数是 double
类上的方法,而不是 System.Math
上的方法。double
类具有 IsNan
和 IsFinite
方法,分别对应于 math.h 中的 isnan
和 isfinite
方法。(Visual Studio 的 math.h 版本有一个 _isnan
函数,但没有对应于 isfinite
的函数。)
数值极限
C# 中的数值极限对于 C 和 C++ 程序员来说有一些出乎意料的地方。
在 C# 中,double.MaxValue
是 double
的最大有限值,对应于 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_MAX
、DBL_MIN
和 DBL_EPSILON
对应于 C++ 中 numeric_limits<double>
的 max
、min
和 epsilon
方法的返回值。)
这是等效的 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_MIN
和 double.MinValue
不同,因为它们在不同的范围内进行最小化。DBL_MIN
是已标准化 double
的最小**正**值,而 C# 中的 double.MinValue
是 double
的最小(即最负)有限值。
C 常量 DBL_EPSILON
是最小的正双精度数 x
,使得 1 + x
不等于 1。通常,双精度数有大约 15 位精度,因此 DBL_EPSILON
的数量级为 10-16。(有关更精确的描述,请参阅 浮点数结构。)
C# 没有对应 DBL_EPSILON
的常量。C# 中的常量 double.Epsilon
类似于 C 常量 DBL_MIN
。 double.Epsilon
是 double
的最小可能正值,包括**非标准化**值。DBL_MIN
是限制为**标准化**值的 double
的最小正值。
缺失的功能
C# 中的数学函数列表非常有限。一些缺失的功能可以轻松地得到补充。例如,System.Math
不包含反双曲函数 asinh
、acosh
或 atanh
。但这些可以通过以下恒等式计算:
- 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 日:初始版本。