Mathクラスには、基本的な数学関数が用意されています。 これらはいずれもMathクラスの静的メソッドとして提供されます。 ここでは、Mathクラスのメソッドについて解説します。
Mathクラスで使用することができる数学関数・数値演算と、対応するメソッドを表にまとめると次のようになります。 個々のメソッドの詳細については順に解説していきます。
関数 | 対応するメソッド呼び出し | 解説 | ||
---|---|---|---|---|
絶対値・符合 | 絶対値 |x| | Math.Abs(x) | 解説へ | |
符号関数 sgn x | Math.Sign(x) | |||
最大・最小 | 最大 max(x, y) | Math.Max(x, y) | 解説へ | |
最小 min(x, y) | Math.Min(x, y) | |||
丸め・端数処理 | 天井関数 ⌈x⌉ | Math.Ceiling(x) | 解説へ | |
床関数 ⌊x⌋ | Math.Floor(x) | |||
切り捨て trunc(x), fix(x) | Math.Truncate(x) | |||
四捨五入 | Math.Round(x, MidpointRounding.AwayFromZero) | |||
最近接偶数への丸め round(x) | Math.Round(x, MidpointRounding.ToEven) | |||
累乗・累乗根 | 累乗 xy | Math.Pow(x, y) | 解説へ | |
ネイピア数の累乗 ex | Math.Exp(x) | |||
平方根 √x | Math.Sqrt(x) | |||
累乗根 n√x | Math.Pow(x, 1.0 / n) | |||
対数 | 自然対数 ln x | Math.Log(x) | 解説へ | |
常用対数 log10x | Math.Log10(x) | |||
対数 logax | Math.Log(x, a) | |||
三角関数 | 三角関数 | sin x | Math.Sin(x) | 解説へ |
cos x | Math.Cos(x) | |||
tan x | Math.Tan(x) | |||
逆正接 tan-1 (y/x) 直交座標(x, y)の偏角 |
Math.Atan2(y, x) | 解説へ | ||
逆三角関数 | sin-1x | Math.Asin(x) | 解説へ | |
cos-1x | Math.Acos(x) | |||
tan-1x | Math.Atan(x) | |||
双曲線関数 | sinh x | Math.Sinh(x) | 解説へ | |
cosh x | Math.Cosh(x) | |||
tanh x | Math.Tanh(x) | |||
関数 | 対応するメソッド呼び出し | 解説 |
Mathクラスのメソッドの使い方
Mathクラスで提供される数学関数はいずれも静的メソッドとなっているため、他のクラスの静的メソッドと同様にクラス名.メソッド(引数)
の形式で呼び出します。
using System;
class Sample {
static void Main()
{
// 3の平方根を求める(Sqrtメソッドを呼び出す)
double val = Math.Sqrt(3);
Console.WriteLine(val);
}
}
Imports System
Class Sample
Shared Sub Main()
' 3の平方根を求める(Sqrtメソッドを呼び出す)
Dim val As Double = Math.Sqrt(3)
Console.WriteLine(val)
End Sub
End Class
1.73205080756888
C# 6.0以降ではusing static
ディレクティブ、VB 7以降ではImports
ステートメントでクラス名を指定することにより、クラス名を省略してメソッドを呼び出すことができるようになります。 これを用いることで、次のようにMathクラスの記述を省略してメソッド呼び出しを行えます。
using System;
using static System.Math; // Mathクラスの静的メンバをインポート(C# 6.0以降)
class Sample {
static void Main()
{
double val = Sqrt(3); // クラス名を省略して呼び出すことができる
Console.WriteLine(val);
}
}
Imports System
Imports System.Math ' Mathクラスのメンバをインポート(VB 7以降)
Class Sample
Shared Sub Main()
Dim val As Double = Sqrt(3) ' クラス名を省略して呼び出すことができる
Console.WriteLine(val)
End Sub
End Class
これはMathクラスのメソッドを多用するコードで特に有用ですが、不必要に濫用すればどのクラスのメソッドを呼び出しているかわかりにくくなるというデメリットもあります。
6.0より前のC#では、using
ディレクティブは名前空間のみにしか使用できないので、静的メンバをインポートによるクラス名の省略はできません。 ただ、using
ディレクティブでクラス名にエイリアス(別名)を付けることができるため、これを用いて短い記述にすることは可能です。 VBのImports
ステートメントでも同様にエイリアスを付けることが出来ます。
using System;
// using System.Math; // usingディレクティブは型名には使用できず、名前空間に対してのみ使用できる
// usingディレクティブで型のエイリアス(別名)を付ける
// ここではSystem.MathクラスにMというエイリアスを与えている
// (M.***と記述するとSystem.Mathのメンバを呼び出せる)
using M = System.Math;
class Sample {
static void Main()
{
double val = M.Sqrt(3); // エイリアスを使って呼び出すことができる
Console.WriteLine(val);
}
}
Imports System
' Importsステートメントで型のエイリアス(別名)を付ける
' ここではSystem.MathクラスにMというエイリアスを与えている
' (M.***と記述するとSystem.Mathのメンバを呼び出せる)
Imports M = System.Math
Class Sample
Shared Sub Main()
Dim val As Double = M.Sqrt(3) ' エイリアスを使って呼び出すことができる
Console.WriteLine(val)
End Sub
End Class
さらに、Mathクラスのメソッド名はすべてPascal形式となっている(大文字から始まる)ので、C#のように大文字・小文字の違いを意識する言語では、呼び出すメソッド名をすべて小文字にするとコンパイルエラーとなります。 C言語のmath.h
の関数(sqrt
やsin
など)を使っているコードを移植するような場合には注意が必要です。
using System;
class Sample {
static void Main()
{
double val = Math.sqrt(3); // error CS0117: `System.Math' に `sqrt' の定義がありません。
Console.WriteLine(val);
}
}
using System;
using static System.Math;
class Sample {
static void Main()
{
double val = sqrt(3); // error CS0103: 名前 `sqrt' は現在のコンテキスト内に存在しません。
Console.WriteLine(val);
}
}
絶対値・符号 (Abs, Sign)
絶対値を求めるにはAbsメソッド、値の符号(正負)を求めるにはSignメソッドを使用します。 Absメソッド・Signメソッドともに戻り値は引数と同じ型になります。 Signメソッドでは、引数の値が正の場合は+1、負の場合は-1、0の場合は0が返されます。
using System;
class Sample {
static void Main()
{
// 絶対値
Console.WriteLine("Abs(3) = {0}", Math.Abs(3));
Console.WriteLine("Abs(-5) = {0}", Math.Abs(-5));
Console.WriteLine("Abs(-3.14) = {0}", Math.Abs(-3.14));
// 符号
Console.WriteLine("Sign(3) = {0}", Math.Sign(3));
Console.WriteLine("Sign(-3.14) = {0}", Math.Sign(-3.14));
Console.WriteLine("Sign(0) = {0}", Math.Sign(0));
}
}
Imports System
Class Sample
Shared Sub Main()
' 絶対値
Console.WriteLine("Abs(3) = {0}", Math.Abs(3))
Console.WriteLine("Abs(-5) = {0}", Math.Abs(-5))
Console.WriteLine("Abs(-3.14) = {0}", Math.Abs(-3.14))
' 符号
Console.WriteLine("Sign(3) = {0}", Math.Sign(3))
Console.WriteLine("Sign(-3.14) = {0}", Math.Sign(-3.14))
Console.WriteLine("Sign(0) = {0}", Math.Sign(0))
End Sub
End Class
Abs(3) = 3 Abs(-5) = 5 Abs(-3.14) = 3.14 Sign(3) = 1 Sign(-3.14) = -1 Sign(0) = 0
Absメソッドと整数最小値のオーバーフロー
整数型の場合、AbsメソッドでMinValueと同じ値の絶対値を求めようとするとオーバーフローとなるためOverflowExceptionがスローされる点に注意が必要です。 これは、例えばintの最小値(int.MinValue)である-2147483648
の絶対値+2147483648
は、intの最大値(int.MaxValue)である+2147483647
を超えていて、intの範囲内で表せないためです。
using System;
class Sample {
static void Main()
{
try {
Console.WriteLine(Math.Abs(int.MinValue)); // intの最小値
}
catch (OverflowException ex) {
Console.WriteLine(ex);
}
try {
Console.WriteLine(Math.Abs(long.MinValue)); // longの最小値
}
catch (OverflowException ex) {
Console.WriteLine(ex);
}
}
}
Imports System
Class Sample
Shared Sub Main()
Try
Console.WriteLine(Math.Abs(Integer.MinValue)) ' Integerの最小値
Catch ex As OverflowException
Console.WriteLine(ex)
End Try
Try
Console.WriteLine(Math.Abs(Long.MinValue)) ' Longの最小値
Catch ex As OverflowException
Console.WriteLine(ex)
End Try
End Sub
End Class
System.OverflowException: 2 の補数の最小値を無効にすることはできません。 場所 System.Math.AbsHelper(Int32 value) 場所 Sample.Main() System.OverflowException: 2 の補数の最小値を無効にすることはできません。 場所 System.Math.AbsHelper(Int64 value) 場所 Sample.Main()
型と最小値・最大値については型の種類・サイズ・精度・値域 §.型のサイズ・精度と値域、オーバーフロー時の動作の変更については整数型のオーバーフローとチェックをご覧ください。
Signメソッドと無限大(±∞)と非数(NaN)の扱い
Double型の場合、値が無限大でもSignメソッドは適切な符号を返しますが、非数(NaN, 0/0)の場合はArithmeticExceptionをスローします。
using System;
class Sample {
static void Main()
{
Console.WriteLine(Math.Sign(+1.0 / 0.0));
Console.WriteLine(Math.Sign(-1.0 / 0.0));
Console.WriteLine(Math.Sign( 0.0 / 0.0));
}
}
Imports System
Class Sample
Shared Sub Main()
Console.WriteLine(Math.Sign(+1.0 / 0.0))
Console.WriteLine(Math.Sign(-1.0 / 0.0))
Console.WriteLine(Math.Sign( 0.0 / 0.0))
End Sub
End Class
1 -1 ハンドルされていない例外: System.ArithmeticException: 関数は浮動小数点の非数値を受け入れません。 場所 System.Math.Sign(Double value) 場所 Sample.Main()
最大・最小 (Min, Max)
二つの値のうち大きい方を求めるにはMaxメソッド、小さい方を求めるにはMinメソッドを使用します。 Maxメソッド・Minメソッドも、戻り値は引数と同じ型になります。
using System;
class Sample {
static void Main()
{
Console.WriteLine(Math.Max(1, 3));
Console.WriteLine(Math.Max(3, 1));
Console.WriteLine(Math.Max(3.14, -1.23));
Console.WriteLine();
Console.WriteLine(Math.Min(1, 3));
Console.WriteLine(Math.Min(3, 1));
Console.WriteLine(Math.Min(3.14, -1.23));
Console.WriteLine();
}
}
Imports System
Class Sample
Shared Sub Main()
Console.WriteLine(Math.Max(1, 3))
Console.WriteLine(Math.Max(3, 1))
Console.WriteLine(Math.Max(3.14, -1.23))
Console.WriteLine()
Console.WriteLine(Math.Min(1, 3))
Console.WriteLine(Math.Min(3, 1))
Console.WriteLine(Math.Min(3.14, -1.23))
Console.WriteLine()
End Sub
End Class
3 3 3.14 1 1 -1.23
3組以上の値の最大値・最小値
Maxメソッド・Minメソッドともに引数は2つしかとらないため、3つ以上の値から最大値・最小値を求めたい場合、複数回呼び出す必要があります。
using System;
class Sample {
static void Main()
{
Console.WriteLine("max = {0}", Math.Max(3, Math.Max(5, 1)));
Console.WriteLine("min = {0}", Math.Min(3, Math.Min(5, 1)));
}
}
Imports System
Class Sample
Shared Sub Main()
Console.WriteLine("max = {0}", Math.Max(3, Math.Max(5, 1)))
Console.WriteLine("min = {0}", Math.Min(3, Math.Min(5, 1)))
End Sub
End Class
max = 5 min = 1
配列内・コレクション内の最大値・最小値
配列やコレクションなどから最大値・最小値を求める場合は、LINQの拡張メソッドMaxメソッドまたはMinメソッドを使うこともできます。
using System;
using System.Linq; // LINQの拡張メソッドを使用するために必要
class Sample {
static void Main()
{
int[] values = new int[] {3, 1, 6, 4, 5, 2};
Console.WriteLine("max = {0}", values.Max());
Console.WriteLine("min = {0}", values.Min());
}
}
Imports System
Imports System.Linq ' LINQの拡張メソッドを使用するために必要
Class Sample
Shared Sub Main()
Dim values As Integer() = New Integer() {3, 1, 6, 4, 5, 2}
Console.WriteLine("max = {0}", values.Max())
Console.WriteLine("min = {0}", values.Min())
End Sub
End Class
max = 6 min = 1
値がSortedSetに格納されている場合は、SortedSet.Maxプロパティ・SortedSet.Minプロパティを使うことでも最大値・最小値を求めることも出来ます。 詳しくはジェネリックコレクション(7) HashSetとSortedSetをご覧ください。
実数の丸め・端数処理 (Truncate, Ceiling, Floor, Round)
Double・Decimalの丸め・端数処理を行うには、次のメソッドを使用します。 目的に応じて5種類の丸め方法を用いることができます。 各メソッドの動作は次のとおりです。
- Truncate (切り捨て)
- 指定した数値の端数部分を切り捨てた整数(数直線上で0の方向にある次の整数)に丸められる。
- Ceiling (正の無限大への丸め)
- 指定した数値以下の最大の整数(数直線上で正の方向にある次の整数)に丸められる。
- Floor (負の無限大への丸め)
- 指定した数値以上の最小の整数(数直線上で負の方向にある次の整数)に丸められる。
- Round
- 丸めの方法MidpointRoundingを指定して整数への丸めを行います。 特に指定しなかった場合はMidpointRounding.ToEvenの動作になります。
- MidpointRounding.ToEven (最近接偶数への丸め、銀行家丸め)
- 数値の端数は偶数方向に丸められる。
- MidpointRounding.AwayFromZero (四捨五入)
- 数値の端数はゼロから遠い方に丸められる。
using System;
class Sample {
static void Main()
{
// 切り捨て
Console.WriteLine("Truncate(1.5) = {0}", Math.Truncate(1.5));
// 次の整数への切り上げ
Console.WriteLine("Ceiling(1.1) = {0}", Math.Ceiling(1.1));
// 前の整数への切り下げ
Console.WriteLine("Floor(1.9) = {0}", Math.Floor(1.9));
// 四捨五入 (小数点0桁への四捨五入・小数点1桁目での四捨五入)
Console.WriteLine("Round(0.4) = {0}", Math.Round(0.4, 0, MidpointRounding.AwayFromZero));
Console.WriteLine("Round(0.5) = {0}", Math.Round(0.5, 0, MidpointRounding.AwayFromZero));
}
}
Imports System
Class Sample
Shared Sub Main()
' 切り捨て
Console.WriteLine("Truncate(1.5) = {0}", Math.Truncate(1.5))
' 次の整数への切り上げ
Console.WriteLine("Ceiling(1.1) = {0}", Math.Ceiling(1.1))
' 前の整数への切り下げ
Console.WriteLine("Floor(1.9) = {0}", Math.Floor(1.9))
' 四捨五入 (小数点0桁への四捨五入・小数点1桁目での四捨五入)
Console.WriteLine("Round(0.4) = {0}", Math.Round(0.4, 0, MidpointRounding.AwayFromZero))
Console.WriteLine("Round(0.5) = {0}", Math.Round(0.5, 0, MidpointRounding.AwayFromZero))
End Sub
End Class
Truncate(1.5) = 1 Ceiling(1.1) = 2 Floor(1.9) = 1 Round(0.4) = 0 Round(0.5) = 1
これらのメソッドの戻り値はいずれもDoubleもしくはDecimalとなるため、整数型への代入を目的として端数処理する場合は、メソッドを呼び出して端数処理した結果をさらに整数型へとキャストする必要があります。
C#での整数型へのキャストはTruncateメソッドによる切り捨てと同じ動作、VBでのCInt
等による型変換はMidpointRounding.ToEven
を指定したRoundメソッドによる最近接偶数への丸めと同じ動作となります。
各メソッドの端数処理の動作を比較すると次のようになります。 0.25刻みの数について、それぞれのメソッドを使って端数処理した場合の結果を並べています。
value| Ceiling Floor Truncate Round+ToEven Round+AwayFromZero| value -------------------------------------------------------------------------------------------------- 2.75| 3.00 2.00 2.00 3.00 3.00| 2.75 2.50| 3.00 2.00 2.00 2.00 3.00| 2.50 2.25| 3.00 2.00 2.00 2.00 2.00| 2.25 2.00| 2.00 2.00 2.00 2.00 2.00| 2.00 1.75| 2.00 1.00 1.00 2.00 2.00| 1.75 1.50| 2.00 1.00 1.00 2.00 2.00| 1.50 1.25| 2.00 1.00 1.00 1.00 1.00| 1.25 1.00| 1.00 1.00 1.00 1.00 1.00| 1.00 0.75| 1.00 0.00 0.00 1.00 1.00| 0.75 0.50| 1.00 0.00 0.00 0.00 1.00| 0.50 0.25| 1.00 0.00 0.00 0.00 0.00| 0.25 0.00| 0.00 0.00 0.00 0.00 0.00| 0.00 -0.25| 0.00 -1.00 0.00 0.00 0.00| -0.25 -0.50| 0.00 -1.00 0.00 0.00 -1.00| -0.50 -0.75| 0.00 -1.00 0.00 -1.00 -1.00| -0.75 -1.00| -1.00 -1.00 -1.00 -1.00 -1.00| -1.00 -1.25| -1.00 -2.00 -1.00 -1.00 -1.00| -1.25 -1.50| -1.00 -2.00 -1.00 -2.00 -2.00| -1.50 -1.75| -1.00 -2.00 -1.00 -2.00 -2.00| -1.75 -2.00| -2.00 -2.00 -2.00 -2.00 -2.00| -2.00 -2.25| -2.00 -3.00 -2.00 -2.00 -2.00| -2.25 -2.50| -2.00 -3.00 -2.00 -2.00 -3.00| -2.50 -2.75| -2.00 -3.00 -2.00 -3.00 -3.00| -2.75
using System;
class Sample {
static void Main()
{
Console.WriteLine("{0,6}| {1,12} {2,12} {3,12} {4,16} {5,20}| {0,6}",
"value",
"Ceiling",
"Floor",
"Truncate",
"Round+ToEven",
"Round+AwayFromZero");
Console.WriteLine(new string('-', 14 * 7));
for (double d = 2.75; -2.75 <= d; d -= 0.25) {
Console.WriteLine("{0,6:F2}| {1,12:F2} {2,12:F2} {3,12:F2} {4,16:F2} {5,20:F2}| {0,6:F2}",
d,
Math.Ceiling(d),
Math.Floor(d),
Math.Truncate(d),
Math.Round(d, MidpointRounding.ToEven),
Math.Round(d, MidpointRounding.AwayFromZero));
}
}
}
Imports System
Class Sample
Shared Sub Main()
Console.WriteLine("{0,6}| {1,12} {2,12} {3,12} {4,16} {5,20}| {0,6}", _
"value", _
"Ceiling", _
"Floor", _
"Truncate", _
"Round+ToEven", _
"Round+AwayFromZero")
Console.WriteLine(New String("-"c, 14 * 7))
For d As Double = 2.75 To -2.75 Step -0.25
Console.WriteLine("{0,6:F2}| {1,12:F2} {2,12:F2} {3,12:F2} {4,16:F2} {5,20:F2}| {0,6:F2}", _
d, _
Math.Ceiling(d), _
Math.Floor(d), _
Math.Truncate(d), _
Math.Round(d, MidpointRounding.ToEven), _
Math.Round(d, MidpointRounding.AwayFromZero))
Next
End Sub
End Class
有効桁数を指定した丸め
Roundメソッドは丸めを行う小数部分の桁数を第二引数で指定することができます。 例えば、四捨五入を行うMidpointRounding.AwayFromZeroと組み合わせて桁数を指定することで、小数点1桁へ四捨五入する(小数点2桁目で四捨五入)、といったことができます。
using System;
class Sample {
static void Main()
{
Console.WriteLine("{0,8}| {1,12} {2,12} {3,12} {4,12}| {0,8}",
"value",
"Round(0)",
"Round(1)",
"Round(2)",
"Round(3)");
Console.WriteLine(new string('-', 14 * 5));
// 1.5から-1.5まで、0.125刻みの数dについて処理
for (double d = 1.5; -1.5 <= d; d -= 0.125) {
Console.WriteLine("{0,8:F4}| {1,12:F4} {2,12:F4} {3,12:F4} {4,12:F4}| {0,8:F4}",
d,
Math.Round(d, 0, MidpointRounding.AwayFromZero), // 小数点0桁へ四捨五入
Math.Round(d, 1, MidpointRounding.AwayFromZero), // 小数点1桁へ四捨五入
Math.Round(d, 2, MidpointRounding.AwayFromZero), // 小数点2桁へ四捨五入
Math.Round(d, 3, MidpointRounding.AwayFromZero)); // 小数点3桁へ四捨五入
}
}
}
Imports System
Class Sample
Shared Sub Main()
Console.WriteLine("{0,8}| {1,12} {2,12} {3,12} {4,12}| {0,8}", _
"value", _
"Round(0)", _
"Round(1)", _
"Round(2)", _
"Round(3)")
Console.WriteLine(New String("-"c, 14 * 5))
' 1.5から-1.5まで、0.125刻みの数dについて処理
For d As Double = 1.5 To -1.5 Step -0.125
Console.WriteLine("{0,8:F4}| {1,12:F4} {2,12:F4} {3,12:F4} {4,12:F4}| {0,8:F4}", _
d, _
Math.Round(d, 0, MidpointRounding.AwayFromZero), _
Math.Round(d, 1, MidpointRounding.AwayFromZero), _
Math.Round(d, 2, MidpointRounding.AwayFromZero), _
Math.Round(d, 3, MidpointRounding.AwayFromZero))
Next
End Sub
End Class
value| Round(0) Round(1) Round(2) Round(3)| value ---------------------------------------------------------------------- 1.5000| 2.0000 1.5000 1.5000 1.5000| 1.5000 1.3750| 1.0000 1.4000 1.3800 1.3750| 1.3750 1.2500| 1.0000 1.3000 1.2500 1.2500| 1.2500 1.1250| 1.0000 1.1000 1.1300 1.1250| 1.1250 1.0000| 1.0000 1.0000 1.0000 1.0000| 1.0000 0.8750| 1.0000 0.9000 0.8800 0.8750| 0.8750 0.7500| 1.0000 0.8000 0.7500 0.7500| 0.7500 0.6250| 1.0000 0.6000 0.6300 0.6250| 0.6250 0.5000| 0.0000 0.5000 0.5000 0.5000| 0.5000 0.3750| 0.0000 0.4000 0.3800 0.3750| 0.3750 0.2500| 0.0000 0.3000 0.2500 0.2500| 0.2500 0.1250| 0.0000 0.1000 0.1300 0.1250| 0.1250 0.0000| 0.0000 0.0000 0.0000 0.0000| 0.0000 -0.1250| 0.0000 -0.1000 -0.1300 -0.1250| -0.1250 -0.2500| 0.0000 -0.3000 -0.2500 -0.2500| -0.2500 -0.3750| 0.0000 -0.4000 -0.3800 -0.3750| -0.3750 -0.5000| 0.0000 -0.5000 -0.5000 -0.5000| -0.5000 -0.6250| -1.0000 -0.6000 -0.6300 -0.6250| -0.6250 -0.7500| -1.0000 -0.8000 -0.7500 -0.7500| -0.7500 -0.8750| -1.0000 -0.9000 -0.8800 -0.8750| -0.8750 -1.0000| -1.0000 -1.0000 -1.0000 -1.0000| -1.0000 -1.1250| -1.0000 -1.1000 -1.1300 -1.1250| -1.1250 -1.2500| -1.0000 -1.3000 -1.2500 -1.2500| -1.2500 -1.3750| -1.0000 -1.4000 -1.3800 -1.3750| -1.3750 -1.5000| -2.0000 -1.5000 -1.5000 -1.5000| -1.5000
整数の四捨五入
Mathクラスには整数を任意の桁数で四捨五入する、例えば5を10に、49を50に四捨五入するとメソッドは用意されていません。 このような目的には、Math.Roundを使って次のようなコードを実装する必要があります。
using System;
class Sample {
// 整数nのd桁目を四捨五入する
static int RoundInt(int n, int d)
{
// 一旦10^dの逆数で数を小数化してMath.Roundで四捨五入したのち、10^dの倍数で元に戻す
var s = Math.Pow(10.0, d);
return (int)(Math.Round(n / s, 0, MidpointRounding.AwayFromZero) * s);
}
static void Main()
{
// 整数1桁目を四捨五入
Console.WriteLine(RoundInt(4, 1));
Console.WriteLine(RoundInt(5, 1));
Console.WriteLine(RoundInt(15, 1));
Console.WriteLine(RoundInt(24, 1));
Console.WriteLine();
// 整数2桁目を四捨五入
Console.WriteLine(RoundInt(49, 2));
Console.WriteLine(RoundInt(50, 2));
Console.WriteLine(RoundInt(149, 2));
Console.WriteLine();
// 整数3桁目を四捨五入
Console.WriteLine(RoundInt(499, 3));
Console.WriteLine(RoundInt(500, 3));
Console.WriteLine();
}
}
Imports System
Class Sample
' 整数nのd桁目を四捨五入する
Shared Function RoundInt(ByVal n As Integer, ByVal d As Integer) As Integer
' 一旦10^dの逆数で数を小数化してMath.Roundで四捨五入したのち、10^dの倍数で元に戻す
Dim s As Double = Math.Pow(10.0, d)
Return CInt(Math.Round(n / s, 0, MidpointRounding.AwayFromZero) * s)
End Function
Shared Sub Main()
' 整数1桁目を四捨五入
Console.WriteLine(RoundInt(4, 1))
Console.WriteLine(RoundInt(5, 1))
Console.WriteLine(RoundInt(15, 1))
Console.WriteLine(RoundInt(24, 1))
Console.WriteLine()
' 整数2桁目を四捨五入
Console.WriteLine(RoundInt(49, 2))
Console.WriteLine(RoundInt(50, 2))
Console.WriteLine(RoundInt(149, 2))
Console.WriteLine()
' 整数3桁目を四捨五入
Console.WriteLine(RoundInt(499, 3))
Console.WriteLine(RoundInt(500, 3))
Console.WriteLine()
End Sub
End Class
0 10 20 20 0 100 100 0 1000
積・商と剰余 (BigMul, DivRem)
オーバーフローを起こさずにint/Integer同士の積を求めたい場合、BigMulメソッドを用いることができます。 このメソッドは二つのint/Integerを引数にとり、それらの積をlong/Long型で返します。
using System;
class Sample {
static void Main()
{
int a = int.MaxValue;
int b = 2;
Console.WriteLine("{0} * {1} = {2}", a, b, Math.BigMul(a, b));
// 同じ値の積を*演算子で求めるとオーバーフローとなる
Console.WriteLine("{0} * {1} = {2}", a, b, a * b);
}
}
Imports System
Class Sample
Shared Sub Main()
Dim a As Integer = Integer.MaxValue
Dim b As Integer = 2
Console.WriteLine("{0} * {1} = {2}", a, b, Math.BigMul(a, b))
' 同じ値の積を*演算子で求めるとオーバーフローとなる
Console.WriteLine("{0} * {1} = {2}", a, b, a * b)
End Sub
End Class
2147483647 * 2 = 4294967294 ハンドルされていない例外: System.OverflowException: 算術演算の結果オーバーフローが発生しました。 場所 Sample.Main()
2147483647 * 2 = 4294967294 2147483647 * 2 = -2
オーバーフローのチェックの有効/無効の切り替えやその際の動作の違いなどについては整数型のオーバーフローとチェックを参照してください。
DivRemメソッドを用いると、整数同士の除算による商と剰余を同時に求めることができます。 商は戻り値として、剰余はoutパラメータとして返されます。 これは除算演算子/
(VBでは\
)と剰余演算子%
(VBではMod
)の結果を同時に求めるのと同じ結果です。
using System;
class Sample {
static void Main()
{
int a = 5;
int b = 3;
int div, rem; // Math.DivRemメソッドの結果を格納する変数
// aとbの商と剰余を求める
// 商は戻り値divに、剰余はoutパラメータのremに代入される
div = Math.DivRem(a, b, out rem);
Console.WriteLine("{0}÷{1} = {2}…{3}", a, b, div, rem);
// aとbの商と剰余を演算子によって個別に求めた場合
div = a / b;
rem = a % b;
Console.WriteLine("{0}÷{1} = {2}…{3}", a, b, div, rem);
}
}
Imports System
Class Sample
Shared Sub Main()
Dim a As Integer = 5
Dim b As Integer = 3
Dim div, rm As Integer ' Math.DivRemメソッドの結果を格納する変数
' aとbの商と剰余を求める
' 商は戻り値divに、剰余はoutパラメータのremに代入される
div = Math.DivRem(a, b, rm)
Console.WriteLine("{0}÷{1} = {2}…{3}", a, b, div, rm)
' aとbの商と剰余を演算子によって個別に求めた場合
div = a \ b
rm = a Mod b
Console.WriteLine("{0}÷{1} = {2}…{3}", a, b, div, rm)
End Sub
End Class
5÷3 = 1…2 5÷3 = 1…2
累乗・平方根 (Pow, Sqrt)
累乗(べき乗)を求めるにはPowメソッド、平方根を求めるにはSqrtメソッドを使用します。 これらのメソッドは、引数・戻り値ともにDoubleです。 立方根(cbrt
)など、累乗根を直接求めるメソッドはMathクラスには用意されていませんが、Powメソッドに根の逆数(立方根なら⅓)を指定することによって累乗根を求めることができます。
using System;
class Sample {
static void Main()
{
// 累乗 (平方・立方)
Console.WriteLine("3^2 = {0}", Math.Pow(3, 2));
Console.WriteLine("2^3 = {0}", Math.Pow(2, 3));
// 平方根
Console.WriteLine("√2 = {0}", Math.Sqrt(2));
Console.WriteLine("√4 = {0}", Math.Sqrt(4));
// 累乗根 (立方根)
Console.WriteLine("^3√8 = {0}", Math.Pow(8, 1.0 / 3.0));
}
}
Imports System
Class Sample
Shared Sub Main()
// 累乗 (平方・立方)
Console.WriteLine("3^2 = {0}", Math.Pow(3, 2))
Console.WriteLine("2^3 = {0}", Math.Pow(2, 3))
// 平方根
Console.WriteLine("√2 = {0}", Math.Sqrt(2))
Console.WriteLine("√4 = {0}", Math.Sqrt(4))
// 累乗根 (立方根)
Console.WriteLine("^3√8 = {0}", Math.Pow(8, 1 / 3))
End Sub
End Class
3^2 = 9 2^3 = 8 √2 = 1.4142135623731 √4 = 2 ^3√8 = 2
VBには累乗演算子 ^ が用意されているので、これを用いることでも累乗・累乗根を求めることもできます。
Imports System
Class Sample
Shared Sub Main()
' 累乗 (平方・立方)
Console.WriteLine("3^2 = {0}", 3 ^ 2)
Console.WriteLine("2^3 = {0}", 2 ^ 3)
' 平方根
Console.WriteLine("√2 = {0}", 2 ^ (1 / 2))
Console.WriteLine("√4 = {0}", 4 ^ (1 / 2))
' 立方根
Console.WriteLine("^3√8 = {0}", 8 ^ (1 / 3))
End Sub
End Class
3^2 = 9 2^3 = 8 √2 = 1.4142135623730951 √4 = 2 ^3√8 = 2
ネイピア数eの累乗を求めるには、Expメソッドを使用することもできます。 なお、ネイピア数eはMath.Eフィールドを参照することで得られるので、わざわざ定数を定義する必要はありません。
using System;
class Sample {
static void Main()
{
Console.WriteLine(Math.Exp(1));
Console.WriteLine(Math.Pow(Math.E, 1)); // Math.Powメソッドを使って求める場合
Console.WriteLine();
Console.WriteLine(Math.Exp(2));
Console.WriteLine(Math.Pow(Math.E, 2)); // Math.Powメソッドを使って求める場合
Console.WriteLine();
}
}
Imports System
Class Sample
Shared Sub Main()
Console.WriteLine(Math.Exp(1))
Console.WriteLine(Math.Pow(Math.E, 1)) ' Math.Powメソッドを使って求める場合
Console.WriteLine()
Console.WriteLine(Math.Exp(2))
Console.WriteLine(Math.Pow(Math.E, 2)) ' Math.Powメソッドを使って求める場合
Console.WriteLine()
End Sub
End Class
2.71828182845905 2.71828182845905 7.38905609893065 7.38905609893065
ユークリッド距離・直角三角形の斜辺の長さ (hypot)
Mathクラスにはユークリッド距離/直角三角形の斜辺の長さを求めるhypot
関数のようなメソッドは用意されていないため、Powメソッド・Sqrtメソッドを組み合わせて計算する必要があります。
using System;
class Sample {
static void Main()
{
double a = 3;
double b = 4;
Console.WriteLine("hypot({0}, {1}) = {2}", a, b, Math.Sqrt(Math.Pow(a, 2.0) + Math.Pow(b, 2.0)));
}
}
Imports System
Class Sample
Shared Sub Main()
Dim a As Double = 3
Dim b As double = 4
Console.WriteLine("hypot({0}, {1}) = {2}", a, b, Math.Sqrt(Math.Pow(a, 2.0) + Math.Pow(b, 2.0)))
End Sub
End Class
hypot(3, 4) = 5
対数 (Log, Log10)
対数を求めるにはLogメソッドを使用します。 このメソッドは任意の底を指定することもできます。 logaxを求めるには、Math.Log(x, a)として呼び出します。 底を指定しない場合は、ネイピア数eを底とした自然対数lnとなります。 また、底を10とした常用対数log10xを求めるにはLog10メソッドを使用することができます。 これらのメソッドは、いずれも引数・戻り値ともにDoubleです。
using System;
class Sample {
static void Main()
{
// 自然対数ln
Console.WriteLine("ln(2.7182818) = {0}", Math.Log(2.7182818)); // eを底とした自然対数
Console.WriteLine("log_e(2.7182818) = {0}", Math.Log(2.7182818, Math.E)); // 上と同等
Console.WriteLine();
// 常用対数log10
Console.WriteLine("log_10(2) = {0}", Math.Log10(2)); // 10を底とした常用対数
Console.WriteLine("log_10(100) = {0}", Math.Log(100, 10)); // 上と同等
Console.WriteLine();
// 底を2とした対数
Console.WriteLine("log_2(2) = {0}", Math.Log(2, 2));
Console.WriteLine("log_2(4) = {0}", Math.Log(4, 2));
Console.WriteLine();
}
}
Imports System
Class Sample
Shared Sub Main()
' 自然対数ln
Console.WriteLine("ln(2.7182818) = {0}", Math.Log(2.7182818)) ' eを底とした自然対数
Console.WriteLine("log_e(2.7182818) = {0}", Math.Log(2.7182818, Math.E)) ' 上と同等
Console.WriteLine()
' 常用対数log10
Console.WriteLine("log_10(2) = {0}", Math.Log10(2)) ' 10を底とした常用対数
Console.WriteLine("log_10(100) = {0}", Math.Log(100, 10)) ' 上と同等
Console.WriteLine()
' 底を2とした対数
Console.WriteLine("log_2(2) = {0}", Math.Log(2, 2))
Console.WriteLine("log_2(4) = {0}", Math.Log(4, 2))
Console.WriteLine()
End Sub
End Class
ln(2.7182818) = 0.999999989530502 log_e(2.7182818) = 0.999999989530502 log_10(2) = 0.301029995663981 log_10(100) = 2 log_2(2) = 1 log_2(4) = 2
Math.Log10メソッドを使うことで10進数数値の桁数を求めることができます。 Math.Log10メソッドやその他の手法で数の桁数を求める方法を数の桁数を求めるで解説しています。
2進対数(⌊log2n⌋・⌊lb n⌋)を求めたい場合、BitOperations.Log2メソッドを使うこともできます。
Logメソッド・Log10メソッドでは、0の対数を求めようとすると∞(無限大)が返されます。 底が1未満の場合は正の無限大(+∞)、底が1より大きい場合は負の無限大(-∞)が返されます。
using System;
class Sample {
static void Main()
{
// log_10(0)
Console.WriteLine(Math.Log10(0));
// log_1/2(0)
Console.WriteLine(Math.Log(0, 0.5));
}
}
Imports System
Class Sample
Shared Sub Main()
' log_10(0)
Console.WriteLine(Math.Log10(0))
' log_1/2(0)
Console.WriteLine(Math.Log(0, 0.5))
End Sub
End Class
-Infinity Infinity
三角関数・双曲線関数 (Sin, Cos, Tan, etc.)
三角関数・三角比を求める関数はそれぞれSinメソッド、Cosメソッド、Tanメソッドとして用意されています。 いずれも、角度の単位はラジアン(rad)です。 度数法・弧度法の変換(度⇄ラジアン)を行うメソッドは用意されていないので、必要に応じて変換処理を書く必要があります。 なお、円周率πはMath.PIフィールドを参照することで得られるので、わざわざ定数を定義する必要はありません。
using System;
class Sample {
static void Main()
{
Console.WriteLine("Sin(π/6) = {0}", Math.Sin(Math.PI / 6));
Console.WriteLine("Cos(π/4) = {0}", Math.Cos(Math.PI / 4));
Console.WriteLine("Tan(π/3) = {0}", Math.Tan(Math.PI / 3));
Console.WriteLine();
double degree = 45.0;
double radian = Math.PI * degree / 180.0; // 度数法(度)から弧度法(ラジアン)に変換
Console.WriteLine("Sin({0}°) = {1}", degree, Math.Sin(radian));
Console.WriteLine("Cos({0}°) = {1}", degree, Math.Cos(radian));
Console.WriteLine("Tan({0}°) = {1}", degree, Math.Tan(radian));
}
}
Imports System
Class Sample
Shared Sub Main()
Console.WriteLine("Sin(π/6) = {0}", Math.Sin(Math.PI / 6))
Console.WriteLine("Cos(π/4) = {0}", Math.Cos(Math.PI / 4))
Console.WriteLine("Tan(π/3) = {0}", Math.Tan(Math.PI / 3))
Console.WriteLine()
Dim degree As Double = 45.0
Dim radian As Double = Math.PI * degree / 180.0 ' 度数法(度)から弧度法(ラジアン)に変換
Console.WriteLine("Sin({0}°) = {1}", degree, Math.Sin(radian))
Console.WriteLine("Cos({0}°) = {1}", degree, Math.Cos(radian))
Console.WriteLine("Tan({0}°) = {1}", degree, Math.Tan(radian))
End Sub
End Class
Sin(π/6) = 0.5 Cos(π/4) = 0.707106781186548 Tan(π/3) = 1.73205080756888 Sin(45°) = 0.707106781186547 Cos(45°) = 0.707106781186548 Tan(45°) = 1
逆三角関数はそれぞれAsinメソッド、Acosメソッド、Atanメソッドとして用意されています。 Sin・Cos・Tanの各メソッドと同様、結果はラジアンで返されます。
using System;
class Sample {
static void Main()
{
Console.WriteLine("Asin(0.5) = {0}", Math.Asin(0.5));
Console.WriteLine("Acos(0.7071) = {0}", Math.Acos(0.7071));
Console.WriteLine("Atan(1.0) = {0}", Math.Atan(1.0));
}
}
Imports System
Class Sample
Shared Sub Main()
Console.WriteLine("Asin(0.5) = {0}", Math.Asin(0.5))
Console.WriteLine("Acos(0.7071) = {0}", Math.Acos(0.7071))
Console.WriteLine("Atan(1.0) = {0}", Math.Atan(1.0))
End Sub
End Class
Asin(0.5) = 0.523598775598299 Acos(0.7071) = 0.785407753397449 Atan(1.0) = 0.785398163397448
座標変換などでよく使われる、xとyの二値から角度を求めるような場合にはAtan2メソッドを使用することができます。 Atan2メソッドは-π≦θ≦πの範囲で結果を返します。 また、Atanメソッドとは異なり、Atan2メソッドは引数の象限を考慮します。 そのため、引数y, xの値によってはAtan2メソッドとAtanメソッドで異なる結果となる場合があります。 また、Atan2メソッドでは、引数をy, xの順で指定する点に注意してください。
using System;
class Sample {
static void Main()
{
double x, y;
x = 1.0; y = 1.0;
Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan2(y, x));
Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan(y / x));
Console.WriteLine();
x = 0.0; y = 1.0;
Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan2(y, x));
Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan(y / x));
Console.WriteLine();
x = -1.0; y = -1.0;
Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan2(y, x));
Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan(y / x)); // AtanメソッドとAtan2メソッドで結果が異なる
Console.WriteLine();
}
}
Imports System
Class Sample
Shared Sub Main()
Dim x, y As Double
x = 1.0 : y = 1.0
Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan2(y, x))
Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan(y / x))
Console.WriteLine()
x = 0.0 : y = 1.0
Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan2(y, x))
Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan(y / x))
Console.WriteLine()
x = -1.0 : y = -1.0
Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan2(y, x))
Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan(y / x)) ' AtanメソッドとAtan2メソッドで結果が異なる
Console.WriteLine()
End Sub
End Class
(1, 1) : 0.785398163397448 (1, 1) : 0.785398163397448 (0, 1) : 1.5707963267949 (0, 1) : 1.5707963267949 (-1, -1) : -2.35619449019234 (-1, -1) : 0.785398163397448
複素数を扱う場合はComplex構造体を使うことができます。 Complex構造体では直交形式・極座標形式の複素数を扱い、また相互に変換することもできます。 詳しくは複素数型を参照してください。
乱数
Mathクラスには乱数を取得するメソッドは用意されていません。 乱数が必要な場合はRandomクラスを使います。 詳しくは乱数を参照してください。