使用 C# 通过 .NET Framework BCL 数学 API






4.33/5 (4投票s)
本文旨在帮助可能需要在学校进行数学编程的初学者 C# 学生。
引言
C# 被广泛应用于许多大学的数学课程中。一位专家程序员坚持认为 C# 和 FORTRAN 一样强大。无论如何,本文仅供初学者阅读。这意味着高级或中级开发者应该忽略本文。内容将首先通过代码展示数据类型,然后提供一个使用 System.Math
API 的基本程序。之后,我们将尝试扩展它们并编写代码来例证这些数学 API 的强大功能。BCL 的 System.Math
类提供了基本的数学函数。此类是静态的,并提供了诸如绝对值、向下取整和向上取整、四舍五入和截断、三角函数、指数运算、对数运算、最小值和最大值等方法。让我们看一些使用这些成员的基本代码。在此之前,我们先回顾一下基本整数数据类型。
using System;
public class App
{
public static void Main()
{
Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
typeof(byte).ToString(), sizeof(byte), byte.MinValue, byte.MaxValue);
Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
typeof(char).ToString(), sizeof(char),
(int)char.MinValue, (int)char.MaxValue);
Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
typeof(short).ToString(), sizeof(short),
short.MinValue, short.MaxValue);
Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
typeof(int).ToString(), sizeof(int), int.MinValue, int.MaxValue);
Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
typeof(long).ToString(), sizeof(long), long.MinValue, long.MaxValue);
Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
typeof(sbyte).ToString(), sizeof(sbyte),
sbyte.MinValue, sbyte.MaxValue);
Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
typeof(ushort).ToString(), sizeof(ushort),
ushort.MinValue, ushort.MaxValue);
Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
typeof(uint).ToString(), sizeof(uint), uint.MinValue, uint.MaxValue);
Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
typeof(ulong).ToString(), sizeof(ulong),
ulong.MinValue, ulong.MaxValue);
}
}
请注意 "typeof
" 关键字,它表示数据类型及其覆盖的数值范围。这是输出结果。
System.Byte: bytes: 1, range: [0,255]
System.Char: bytes: 2, range: [0,65535]
System.Int16: bytes: 2, range: [-32768,32767]
System.Int32: bytes: 4, range: [-2147483648,2147483647]
System.Int64: bytes: 8, range: [-9223372036854775808,9223372036854775807]
System.SByte: bytes: 1, range: [-128,127]
System.UInt16: bytes: 2, range: [0,65535]
System.UInt32: bytes: 4, range: [0,4294967295]
System.UInt64: bytes: 8, range: [0,18446744073709551615]
从上面可以看出,我们还没有看到 decimal
、float
或 double
类型。
using System;
public class Program
{
public static void Main()
{
Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
typeof(float).ToString(), sizeof(float), float.MinValue, float.MaxValue);
Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
typeof(double).ToString(), sizeof(double), double.MinValue, double.MaxValue);
Console.WriteLine("{0}: bytes: {1}, range: [{2},{3}]",
typeof(decimal).ToString(), sizeof(decimal), decimal.MinValue, decimal.MaxValue);
}
}
请注意 sizeof
关键字的使用。现在我们看到了这些类型的名称,它们被 CLR 识别,并输出它们的最小值和最大值。
System.Single: bytes: 4, range: [-3.402823E+38,3.402823E+38]
System.Double: bytes: 8,
range: [-1.79769313486232E+308,1.79769313486232E+308]
System.Decimal: bytes: 16,
range: [79228162514264337593543950335,79228162514264337593543950335]
现在我们可以看一个使用 System.Math
API 的例子。
using System;
public class Program
{
public static void Main()
{
Console.WriteLine("Abs({0}) = {1}", -45, Math.Abs(-45));
Console.WriteLine("Ceiling({0}) = {1}", 45.3, Math.Ceiling(45.3));
Console.WriteLine("Pow({0},{1}em;) = {2}", 10.5, 3, Math.Pow(10.5, 3));
Console.WriteLine("Round({0},{1}) = {2}",
10.55358, 2, Math.Round(10.55358, 2));
Console.WriteLine("Sin({0}) = {1}", 323.333, Math.Sin(323.333));
Console.WriteLine("Cos({0}) = {1}", 323.333, Math.Cos(323.333));
Console.WriteLine("Tan({0}) = {1}", 323.333, Math.Tan(323.333));
Console.WriteLine("Sinh({0}) = {1}", 323.333, Math.Sinh(323.333));
Console.WriteLine("Cosh({0}) = {1}", 323.333, Math.Cosh(323.333));
Console.WriteLine("Tanh({0}) = {1}", 323.333, Math.Tanh(323.333));
}
}
输出如下
Abs(-45) = 45
Ceiling(45.3) = 56
Pow(10.5,3em;) = 1157.625
Round(10.55358,2) = 10.55
Sin(323.333) = 0.248414709883854
Cos(323.333) = -0.968653772982546
Tan(323.333) = -0.256453561440193
Sinh(323.333) = 1.3204067066941E+140
Cosh(323.333) = 1.3204067066941E+140
Tanh(323.333) = 1
角度测量单位
我们输入的三角函数数字似乎提供了不寻常的输出。在初等平面几何中,角由两条在同一点相交的射线正式定义。两条射线相交的点称为角的顶点,两条射线本身称为角的边。然后,通过首先绘制一个以角顶点为中心且与两条边都相交的圆弧(设长度为 s),来测量任意角(设为 θ)。然后将弧长 s 除以相应圆的半径 r,得到角 θ = s/r。由于它们被定义为长度的比率,因此角度被认为是无量纲的。尽管如此,有几种单位用于测量角度,最常见的弧度和角度。由长度等于圆半径的弧在圆心处所张的角被定义为一弧度。角度(用上标小圆圈 (◦) 表示)是整个圆的 1/360。因此,一个完整的圆是 360◦ 或 2π 弧度,一弧度是 180◦/π 度,或约 57.2958◦。弧度是公制系统中角度测量的首选单位,缩写为 rad。
这是执行角度和弧度之间转换的代码。
using System;
public class Program {
public static double DegreesToRadians(double degrees)
{
return (Math.PI / 180.0) * degrees;
}
public static double RadiansToDegrees(double radians)
{
return (180.0 / Math.PI) * radians;
}
public static double GradsToRadians(double grads)
{
return (grads / 200.0) * Math.PI;
}
public static double RadiansToGrads(double radians)
{
return (radians / Math.PI) * 200.0;
}
public static double DegreesToGrads(double degrees)
{
return (degrees / 9.0) * 10.0;
}
public static double GradsToDegrees(double grads)
{
return (grads / 10.0) * 9.0;
}
public static double Sec(double x)
{
return (1.0 / Math.Cos(x));
}
public static double Csc(double x)
{
return (1.0 / Math.Sin(x));
}
public static double Cot(double x)
{
return (Math.Cos(x) / Math.Sin(x));
}
public static void Main()
{
Console.WriteLine("\n--- RUNNING TRIG FUNCTIONS EXAMPLE ---\n");
for (double angleDEG = 0.0; angleDEG <= 360.0; angleDEG += 45.0)
{
double angleRAD = DegreesToRadians(angleDEG);
Console.WriteLine("Angle = {0}\xb0", angleDEG);
Console.WriteLine("cos({0}\xb0) = {1}", angleDEG, Math.Cos(angleRAD));
Console.WriteLine("sin({0}\xb0) = {1}", angleDEG, Math.Sin(angleRAD));
Console.WriteLine("tan({0}\xb0) = {1}", angleDEG, Math.Tan(angleRAD));
Console.WriteLine("sec({0}o) = {1}", angleDEG, Sec(angleRAD));
Console.WriteLine("csc({0}o) = {1}", angleDEG, Csc(angleRAD));
Console.WriteLine("cot({0}o) = {1}", angleDEG, Cot(angleRAD));
Console.WriteLine("--------------------------------------------\n");
}
Console.WriteLine("--------------------------------------------\n");
}
}
考虑 45 度角。45 度角的正弦和余弦值都是 0.707。这个数字是二分之一的平方根的倒数。这意味着单位圆形成的三角形的两条边长度为一,另一条边长度为二的平方根。这是输出结果。
--- RUNNING TRIG FUNCTIONS EXAMPLE ---
Angle = 0°
cos(0°) = 1
sin(0°) = 0
tan(0°) = 0
sec(0o) = 1
csc(0o) = Infinity
cot(0o) = Infinity
--------------------------------------------
Angle = 45°
cos(45°) = 0.707106781186548
sin(45°) = 0.707106781186547
tan(45°) = 1
sec(45o) = 1.41421356237309
csc(45o) = 1.4142135623731
cot(45o) = 1
--------------------------------------------
Angle = 90°
cos(90°) = 6.12303176911189E-17
sin(90°) = 1
tan(90°) = 1.63317787283838E+16
sec(90o) = 1.63317787283838E+16
csc(90o) = 1
cot(90o) = 6.12303176911189E-17
--------------------------------------------
Angle = 135°
cos(135°) = -0.707106781186547
sin(135°) = 0.707106781186548
tan(135°) = -1
sec(135o) = -1.4142135623731
csc(135o) = 1.41421356237309
cot(135o) = -1
--------------------------------------------
Angle = 180°
cos(180°) = -1
sin(180°) = 1.22460635382238E-16
tan(180°) = -1.22460635382238E-16
sec(180o) = -1
csc(180o) = 8.16588936419192E+15
cot(180o) = -8.16588936419192E+15
--------------------------------------------
Angle = 225°
cos(225°) = -0.707106781186548
sin(225°) = -0.707106781186547
tan(225°) = 1
sec(225o) = -1.41421356237309
csc(225o) = -1.4142135623731
cot(225o) = 1
--------------------------------------------
Angle = 270°
cos(270°) = -1.83690953073357E-16
sin(270°) = -1
tan(270°) = 5.44392624279462E+15
sec(270o) = -5.44392624279462E+15
csc(270o) = -1
cot(270o) = 1.83690953073357E-16
--------------------------------------------
Angle = 315°
cos(315°) = 0.707106781186547
sin(315°) = -0.707106781186548
tan(315°) = -1
sec(315o) = 1.4142135623731
csc(315o) = -1.41421356237309
cot(315o) = -1
--------------------------------------------
Angle = 360°
cos(360°) = 1
sin(360°) = -2.44921270764475E-16
tan(360°) = -2.44921270764475E-16
sec(360o) = 1
csc(360o) = -4.08294468209596E+15
cot(360o) = -4.08294468209596E+15
--------------------------------------------
好的。这并不算太难,不是吗?现在让我们简要研究一下幂、对数、指数、最小值和最大值运算。.NET Framework 数学类库提供了两种比较数字相对大小的方法。Math.Min
方法返回两个数字中较小的一个,而 Math.Max
方法返回两个数字中较大的一个。具有固定实数基数 b > 1 和实数幂 x 的一般指数函数是指由公式 f (x) = bx 表示的函数。x 被称为指数,表达式 bx 被正式称为 b 的 x 次幂或 b 的指数,或 b 的 x 次幂。它也更常见地表达为b 的 x 次幂、b 的 x 次幂 或 b 的 x 次幂。最常用的基数是自然底数 e 和底数 10。如果基数等于欧拉数 e,则指数函数称为自然指数函数,表示为 f (x) = ex = exp(x)。
任何指数函数的反函数都称为以 b 为底的对数函数,记作 logb。因此 logb bx = x。一个数的以给定正实数为底的对数是该底数必须提高到的幂或指数,才能得到该数。根据定义,x 以 b 为底的对数写为 logb(x),或者如果底数是隐含的,则写为 log(x)。因此,对于一个数 x,一个底数 b 和一个指数 y,如果 x = by,则 y = logb(x)。以下是示例代码,请注意通过检查值来了解反向运算。另外请注意,PI 和 E 的数字也被包含在内,以展示 .NET Framework 如何重复它们的循环小数。
using System;
public static class Program
{
public static void PI_AND_E_Example()
{
Console.WriteLine("--- RUNNING Math.PI and Math.E EXAMPLE ---\n");
Console.WriteLine("PI = {0}", Math.PI);
Console.WriteLine("E = {0}", Math.E);
Console.WriteLine("\n------------------------------------------\n");
}
public static void MinMax_Example()
{
double x = 5.0, y = 10.0;
Console.WriteLine("----- RUNNING Math.Min/Max EXAMPLE -----\n");
Console.WriteLine("The smaller of {0} and {1} is {2}.", x, y, Math.Min(x, y));
Console.WriteLine("The greater of {0} and {1} is {2}.", x, y, Math.Max(x, y));
Console.WriteLine("\n----------------------------------------\n");
}
public static void PowExpLogLog10_Example()
{
double b = 2.75, x = 3.25, newBase = 8;
Console.WriteLine("--- RUNNING Math.Pow/Exp/Log/" +
"Log10/Log(x,newBase) EXAMPLE ---\n");
Console.WriteLine("Exp({0}) = {1}", x, Math.Exp(x));
Console.WriteLine("Log({0}) = {1}\n", Math.Exp(x), Math.Log(Math.Exp(x)));
Console.WriteLine("Pow({0},{1}) = {2}", b, x, Math.Pow(b, x));
Console.WriteLine("Log10({0})/Log10({1}) = {2}\n",
Math.Pow(b, x), b, Math.Log10(Math.Pow(b, x)) / Math.Log10(b));
Console.WriteLine("Log{0}({1}) = {2}", newBase, x, Math.Log(x, newBase));
Console.WriteLine("Pow({0},{1}) = {2}", newBase,
Math.Log(x, newBase), Math.Pow(newBase, Math.Log(x, newBase)));
Console.WriteLine("---------------------------------" +
"----------------------------\n");
}
public static void Main(string[] args)
{
PI_AND_E_Example();
Console.ReadLine();
MinMax_Example();
Console.ReadLine();
PowExpLogLog10_Example();
Console.ReadLine();
}
}
输出如下
--- RUNNING Math.PI and Math.E EXAMPLE ---
PI = 3.14159265358979
E = 2.71828182845905
------------------------------------------
----- RUNNING Math.Min/Max EXAMPLE -----
The smaller of 5 and 10 is 5.
The greater of 5 and 10 is 10.
--- RUNNING Math.Pow/Exp/Log/Log10/Log(x,newBase) EXAMPLE ---
Exp(3.25) = 25.7903399171931
Log(25.7903399171931) = 3.25
Pow(2.75,3.25) = 26.7812753660606
Log10(26.7812753660606)/Log10(2.75) = 3.25 // notice the symmetry
Log8(3.25) = 0.566813239380364
Pow(8,0.566813239380364) = 3.25
反双曲函数
双曲函数与双曲线的关系,就像三角函数与单位圆的关系一样。例如,三角函数 cos x 和 sin x 与半径为 r 的圆有关。
using System;
public static class Program
{
public static double DegreesToRadians(double degrees)
{
return (Math.PI / 180.0) * degrees;
}
public static double RadiansToDegrees(double radians)
{
return (180.0 / Math.PI) * radians;
}
public static double GradsToRadians(double grads)
{
return (grads / 200.0) * Math.PI;
}
public static double RadiansToGrads(double radians)
{
return (radians / Math.PI) * 200.0;
}
public static double DegreesToGrads(double degrees)
{
return (degrees / 9.0) * 10.0;
}
public static double GradsToDegrees(double grads)
{
return (grads / 10.0) * 9.0;
}
public static double ASinh(double x)
{
return (Math.Log(x + Math.Sqrt(x * x + 1.0)));
}
public static double ACosh(double x)
{
return (Math.Log(x + Math.Sqrt((x * x) - 1.0)));
}
public static double ATanh(double x)
{
return (Math.Log((1.0 + x) / (1.0 - x)) / 2.0);
}
public static double ACoth(double x)
{
//return (Math.Log((x + 1.0) / (x - 1.0)) / 2.0);
return (ATanh(1.0 / x));
}
public static double ASech(double x)
{
return (ACosh(1.0 / x));
}
public static double ACsch(double x)
{
return (ASinh(1.0 / x));
}
public static double Sech(double x)
{
return (1.0 / Math.Cosh(x));
}
public static double Csch(double x)
{
return (1.0 / Math.Sinh(x));
}
public static double Coth(double x)
{
return (Math.Cosh(x) / Math.Sinh(x));
}
public static void Main()
{
Console.WriteLine("\n--- RUNNING INVERSE HYPERBOLIC FUNCTIONS EXAMPLE ---\n");
for (double angleDEG = 0.0; angleDEG <= 360.0; angleDEG += 45.0)
{
double angleRAD = DegreesToRadians(angleDEG);
Console.WriteLine("Angle = {0}\xb0", angleDEG);
Console.WriteLine("ACosh({0}) = {1}\xb0",
Math.Cosh(angleRAD), RadiansToDegrees(ACosh(Math.Cosh(angleRAD))));
Console.WriteLine("ASinh({0}) = {1}\xb0",
Math.Sinh(angleRAD), RadiansToDegrees(ASinh(Math.Sinh(angleRAD))));
Console.WriteLine("ATanh({0}) = {1}\xb0",
Math.Tanh(angleRAD), RadiansToDegrees(ATanh(Math.Tanh(angleRAD))));
Console.WriteLine("ASech({0}) = {1}o",
Sech(angleRAD), RadiansToDegrees(ASech(Sech(angleRAD))));
Console.WriteLine("ACsch({0}) = {1}o",
Csch(angleRAD), RadiansToDegrees(ACsch(Csch(angleRAD))));
Console.WriteLine("ACoth({0}) = {1}o",
Coth(angleRAD), RadiansToDegrees(ACoth(Coth(angleRAD))));
Console.WriteLine("--------------------------------------------\n");
}
}
}
输出:
--- RUNNING INVERSE HYPERBOLIC FUNCTIONS EXAMPLE ---
Angle = 0°
ACosh(1) = 0°
ASinh(0) = 0°
ATanh(0) = 0°
ASech(1) = 0o
ACsch(Infinity) = 0o
ACoth(Infinity) = 0o
--------------------------------------------
Angle = 45°
ACosh(1.32460908925201) = 45°
ASinh(0.86867096148601) = 45°
ATanh(0.655794202632672) = 45°
ASech(0.754939708714131) = 45o
ACsch(1.15118387092085) = 45o
ACoth(1.52486861882206) = 45o
--------------------------------------------
Angle = 90°
ACosh(2.50917847865806) = 90°
ASinh(2.30129890230729) = 90°
ATanh(0.917152335667274) = 90°
ASech(0.398536815338387) = 90o
ACsch(0.434537208094696) = 90o
ACoth(1.09033141072737) = 90o
--------------------------------------------
Angle = 135°
ACosh(5.32275214951996) = 135°
ASinh(5.2279719246778) = 135°
ATanh(0.982193380007239) = 135°
ASech(0.187872734237717) = 135o
ACsch(0.191278762473773) = 135o
ACoth(1.01812944411479) = 135o
--------------------------------------------
Angle = 180°
ACosh(11.5919532755215) = 180°
ASinh(11.5487393572577) = 180°
ATanh(0.99627207622075) = 180°
ASech(0.0862667383340544) = 180o
ACsch(0.086589537530047) = 180o
ACoth(1.00374187319732) = 179.999999999999o
--------------------------------------------
Angle = 225°
ACosh(25.3868611923608) = 225°
ASinh(25.3671583193742) = 225°
ATanh(0.999223894878641) = 225°
ASech(0.0393904544726038) = 225o
ACsch(0.0394210493508944) = 225o
ACoth(1.00077670792836) = 225o
--------------------------------------------
Angle = 270°
ACosh(55.6633808904387) = 270°
ASinh(55.6543975994175) = 270°
ATanh(0.999838613988633) = 269.999999999992°
ASech(0.017965132264752) = 270o
ACsch(0.0179680320537773) = 270o
ACoth(1.00016141206102) = 269.999999999992o
--------------------------------------------
Angle = 315°
ACosh(122.077579339582) = 315°
ASinh(122.073483514693) = 315°
ATanh(0.999966448999796) = 315.00000000001°
ASech(0.00819151235967997) = 315o
ACsch(0.00819178720233407) = 315o
ACoth(1.00003355212591) = 315.00000000001o
--------------------------------------------
Angle = 360°
ACosh(267.746761483748) = 360°
ASinh(267.744894041016) = 360°
ATanh(0.999993025339611) = 360.000000000173°
ASech(0.00373487243863713) = 360o
ACsch(0.00373489848828567) = 360o
ACoth(1.00000697470904) = 359.999999999717o
以上源代码只是触及了 C# 和 BCL 的 System.Math
类 API 强大功能的表面。再次重申,本文是为初学者编写的。
参考文献
- MSDN 库
- 专业 .NET Framework 2.0,作者 Joe Duffy