Mathクラスには、基本的な数学関数が用意されています。 これらはいずれも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)
累乗根 nx 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クラスで提供される数学関数はいずれも静的メソッドとなっているため、他のクラスの静的メソッドと同様にクラス名.メソッド(引数)の形式で呼び出します。

Mathクラスのメソッドを呼び出す
using System;

class Sample {
  static void Main()
  {
    // 3の平方根を求める(Sqrtメソッドを呼び出す)
    double val = Math.Sqrt(3);

    Console.WriteLine(val);
  }
}
Mathクラスのメソッドを呼び出す
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 staticディレクティブでMathクラス名の修飾を省略する 
using System;
using static System.Math; // Mathクラスの静的メンバをインポート(C# 6.0以降)

class Sample {
  static void Main()
  {
    double val = Sqrt(3); // クラス名を省略して呼び出すことができる

    Console.WriteLine(val);
  }
}
ImportステートメントでMathクラスのメンバをインポートする 
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ディレクティブでMathクラスにエイリアスを付けて呼び出す
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ステートメントでMathクラスにエイリアスを付けて呼び出す 
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の関数(sqrtsinなど)を使っているコードを移植するような場合には注意が必要です。

メソッド名を誤って小文字にした場合
using System;

class Sample {
  static void Main()
  {
    double val = Math.sqrt(3); // error CS0117: `System.Math' に `sqrt' の定義がありません。

    Console.WriteLine(val);
  }
}
メソッド名を誤って小文字にした場合(C# 6.0以降、using staticディレクティブを使用している場合)
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が返されます。

Math.Abs・Math.Signメソッドを使って値の絶対値と符合を求める
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));
  }
}
Math.Abs・Math.Signメソッドを使って値の絶対値と符合を求める
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の範囲内で表せないためです。

Math.Absメソッドで整数の最小値を指定すると例外OverflowExceptionをスローする
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);
    }
  }
}
Math.Absメソッドで整数の最小値を指定すると例外OverflowExceptionをスローする
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をスローします。

Math.Signメソッドで非数(NaN)を指定すると例外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));
  }
}
Math.Signメソッドで非数(NaN)を指定すると例外ArithmeticExceptionをスローする
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メソッドも、戻り値は引数と同じ型になります。

Math.Max・Math.Minメソッドを使って2つの値のうち大きい方・小さい方を求める
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();
  }
}
Math.Max・Math.Minメソッドを使って2つの値のうち大きい方・小さい方を求める
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つ以上の値から最大値・最小値を求めたい場合、複数回呼び出す必要があります。

Math.Max・Math.Minメソッドを使って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)));
  }
}
Math.Max・Math.Minメソッドを使って3組以上の値から最大値・最小値を求める
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メソッドを使うこともできます。

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());
  }
}
LINQの拡張メソッドMax・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 (四捨五入)
数値の端数はゼロから遠い方に丸められる。
Math.Truncate・Ceiling・Floor・Roundの各メソッドを使って切り捨て・切り上げ・切り下げ・四捨五入を行う
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));
  }
}
Math.Truncate・Ceiling・Floor・Roundの各メソッドを使って切り捨て・切り上げ・切り下げ・四捨五入を行う
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
Truncate・Ceiling・Floor・Roundの各メソッドと丸め・端数処理の結果の違い
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));
    }
  }
}
Truncate・Ceiling・Floor・Roundの各メソッドと丸め・端数処理の結果の違い
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桁目で四捨五入)、といったことができます。

Math.Roundメソッドを使って小数点n桁への四捨五入をする
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桁へ四捨五入
    }
  }
}
Math.Roundメソッドを使って小数点n桁への四捨五入をする
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を使って次のようなコードを実装する必要があります。

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();
  }
}
Math.Roundメソッドを使って整数を任意の桁数で四捨五入をする
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型で返します。

Math.BigMulメソッドを使ってオーバーフローを起こさずに32ビット整数同士の積を求める
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);
  }
}
Math.BigMulメソッドを使ってオーバーフローを起こさずに32ビット整数同士の積を求める
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)の結果を同時に求めるのと同じ結果です。

Math.DivRemメソッドを使って商と剰余を同時に求める
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);
  }
}
Math.DivRemメソッドを使って商と剰余を同時に求める
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メソッドに根の逆数(立方根なら⅓)を指定することによって累乗根を求めることができます。

Math.Pow・Math.Sqrtメソッドを使って累乗・累乗根・平方根を求める
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));
  }
}
Math.Pow・Math.Sqrtメソッドを使って累乗・累乗根・平方根を求める
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メソッドを使用することもできます。 なお、ネイピア数eMath.Eフィールドを参照することで得られるので、わざわざ定数を定義する必要はありません。

Math.Expメソッドを使ってネイピア数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();
  }
}
Math.Expメソッドを使ってネイピア数eの累乗を求める
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メソッドを組み合わせて計算する必要があります。

Math.Powメソッド・Math.Sqrtメソッドを組み合わせてユークリッド距離(hypot)を求める
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)));
  }
}
Math.Powメソッド・Math.Sqrtメソッドを組み合わせてユークリッド距離(hypot)を求める
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です。

Math.Logメソッド・Math.Log10メソッドを使って自然対数・常用対数・任意の底の対数を求める
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();
  }
}
Math.Logメソッド・Math.Log10メソッドを使って自然対数・常用対数・任意の底の対数を求める
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より大きい場合は負の無限大(-∞)が返されます。

Math.Logメソッド・Math.Log10メソッドで0の対数を求めると無限大が返される
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));
  }
}
Math.Logメソッド・Math.Log10メソッドで0の対数を求めると無限大が返される
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フィールドを参照することで得られるので、わざわざ定数を定義する必要はありません。

Math.Sin・Cos・Tanメソッドを使って正弦・余弦・正接を求める
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));
  }
}
Math.Sin・Cos・Tanメソッドを使って正弦・余弦・正接を求める
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の各メソッドと同様、結果はラジアンで返されます。

Math.Asin・Acos・Atanメソッドを使って三角比から角度を求める
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));
  }
}
Math.Asin・Acos・Atanメソッドを使って三角比から角度を求める
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

座標変換などでよく使われる、xyの二値から角度を求めるような場合にはAtan2メソッドを使用することができます。 Atan2メソッドは-π≦θ≦πの範囲で結果を返します。 また、Atanメソッドとは異なり、Atan2メソッドは引数の象限を考慮します。 そのため、引数y, xの値によってはAtan2メソッドとAtanメソッドで異なる結果となる場合があります。 また、Atan2メソッドでは、引数をy, xの順で指定する点に注意してください。

Atan2メソッドを使って座標(x, 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();
  }
}
Atan2メソッドを使って座標(x, y)とx軸のなす角を求める
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構造体では直交形式・極座標形式の複素数を扱い、また相互に変換することもできます。 詳しくは複素数型を参照してください。


双曲線関数はそれぞれSinhメソッドCoshメソッドTanhメソッドとして用意されています。

乱数

Mathクラスには乱数を取得するメソッドは用意されていません。 乱数が必要な場合はRandomクラスを使います。 詳しくは乱数を参照してください。