2011-06-24T23:41:05の更新内容

programming/netfx/mathematics/1_random/index.wiki.txt

current previous
1,772 0,0
+
${smdncms:title,乱数}
+
${smdncms:header_title,乱数 (System.Random)}
+
${smdncms:keywords,乱数,Random}
+

          
+
#navi(..)
+

          
+
ここでは疑似乱数を取得するためのクラス&msdn(netfx,type,System.Random){Randomクラス};と暗号乱数ジェネレーター&msdn(netfx,type, System.Security.Cryptography.RandomNumberGenerator){RandomNumberGeneratorクラス};について解説します。
+

          
+
-関連するページ
+
--[[programming/tips/shuffle_array]]
+

          
+
#googleadunit(banner)
+

          
+
*Randomクラス
+
乱数を得るには、&msdn(netfx,type,System.Random){Randomクラス};を使用します。 このクラスはMathクラスとは異なり、使用するにはインスタンスを生成する必要があります。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // Randomクラスのインスタンスを作成
+
    Random rand = new Random();
+

          
+
    // 0以上100未満の乱数を20回取得して表示する
+
    for (int i = 0; i < 20; i++)
+
    {
+
      Console.Write("{0} ", rand.Next(0, 100));
+
    }
+

          
+
    Console.WriteLine();
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    ' Randomクラスのインスタンスを作成
+
    Dim rand As New Random()
+

          
+
    ' 0以上100未満の乱数を20回取得して表示する
+
    For i As Integer = 1 To 20
+
      Console.Write("{0} ", rand.Next(0, 100))
+
    Next
+

          
+
    Console.WriteLine()
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果の一例){{
+
16 47 34 79 33 54 80 41 99 37 14 86 52 54 52 20 8 31 59 44 
+
}}
+

          
+
**乱数の取得
+
Randomクラスには、乱数を得るためのメソッドがいくつか用意されています。 求める乱数の範囲・種類によって次のメソッドを使い分けることができます。 なお、いずれも得られる乱数の範囲は半開区間(n以上m未満)となっています。
+

          
+
:&msdn(netfx,member,System.Random.NextDouble){NextDoubleメソッド};|0.0以上1.0未満の乱数を実数(Double)で取得する。 [0.0, 1.0)
+
:&msdn(netfx,member,System.Random.Next){Nextメソッド};|乱数を整数(Int32)で取得する。
+
::Next()|0以上の乱数を取得する。 [0, Int32.MaxValue)
+
::Next(max)|0以上max未満の乱数を取得する。 [0, max)
+
::Next(min, max)|min以上max未満の乱数を取得する。 [min, max)
+

          
+
なお、NextDoubleメソッドには範囲を指定するバージョンは用意されていません。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Random rand = new Random();
+

          
+
    for (int i = 0; i < 20; i++)
+
    {
+
      // 1以上6以下(7未満)の乱数
+
      Console.Write("{0} ", rand.Next(1, 7));
+
    }
+

          
+
    Console.WriteLine();
+

          
+
    for (int i = 0; i < 20; i++)
+
    {
+
      // [-1.0, 1.0)の乱数
+
      Console.Write("{0:F2} ", 2.0 * rand.NextDouble() - 1.0);
+
    }
+

          
+
    Console.WriteLine();
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim rand As New Random()
+

          
+
    For i As Integer = 1 To 20
+
      ' 1以上6以下(7未満)の乱数
+
      Console.Write("{0} ", rand.Next(1, 7))
+
    Next
+

          
+
    Console.WriteLine()
+

          
+

          
+
    For i As Integer = 1 To 20
+
      ' [-1.0, 1.0)の乱数
+
      Console.Write("{0:F2} ", 2.0 * rand.NextDouble() - 1.0)
+
    Next
+

          
+
    Console.WriteLine()
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果の一例){{
+
1 6 4 6 6 5 3 5 5 2 2 4 3 3 4 6 4 3 1 2 
+
0.56 -0.21 0.47 0.00 0.65 -0.27 0.21 0.98 -0.66 -0.26 0.01 -0.87 0.97 0.94 0.05 0.82 0.40 -0.27 0.72 -0.85 
+
}}
+

          
+
&msdn(netfx,member,System.Random.NextBytes){NextBytesメソッド};を使うと、バイト配列を0からByte.MaxValue(255)までのランダムな値で満たすことができます。 このメソッドを使うことでnonce値の生成などを行うことができます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    byte[] nonce = new byte[16];
+
    Random rand = new Random();
+

          
+
    // NextBytesを使って配列をランダムな値で満たす
+
    rand.NextBytes(nonce);
+

          
+
    Console.WriteLine(BitConverter.ToString(nonce));
+
    Console.WriteLine(Convert.ToBase64String(nonce));
+
    Console.WriteLine();
+

          
+
    // NextBytesを使わないで同じ処理を行う例
+
    for (int i = 0; i < nonce.Length; i++)
+
    {
+
      nonce[i] = (byte)rand.Next(0, byte.MaxValue + 1);
+
    }
+

          
+
    Console.WriteLine(BitConverter.ToString(nonce));
+
    Console.WriteLine(Convert.ToBase64String(nonce));
+
    Console.WriteLine();
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim nonce(15) As Byte
+
    Dim rand As New Random()
+

          
+
    ' NextBytesを使って配列をランダムな値で満たす
+
    rand.NextBytes(nonce)
+

          
+
    Console.WriteLine(BitConverter.ToString(nonce))
+
    Console.WriteLine(Convert.ToBase64String(nonce))
+
    Console.WriteLine()
+

          
+
    ' NextBytesを使わないで同じ処理を行う例
+
    For i As Integer = 0 To nonce.Length - 1
+
      nonce(i) = CByte(rand.Next(0, Byte.MaxValue + 1))
+
    Next
+

          
+
    Console.WriteLine(BitConverter.ToString(nonce))
+
    Console.WriteLine(Convert.ToBase64String(nonce))
+
    Console.WriteLine()
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果の一例){{
+
5D-DA-A5-7C-17-F5-12-FD-28-12-77-27-8C-41-33-D1
+
XdqlfBf1Ev0oEncnjEEz0Q==
+

          
+
D1-B4-14-B1-6B-E2-C5-96-58-03-CD-3D-68-43-24-EA
+
0bQUsWvixZZYA809aEMk6g==
+

          
+
}}
+

          
+
**乱数のシード
+
Randomクラスでは、一つのインスタンスが一つの乱数系列として動作します。 個々のインスタンスに異なるシード値(乱数の種)を与えることで複数の乱数系列を生成することができます。 シード値はRandomクラスのコンストラクタで指定することができ、同一のシード値を与えた場合は同一の乱数系列となります。 インスタンスを生成したときのシード値を保存しておくことで、前回と同じ乱数を取得するという使い方もできます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Random rand1 = new Random(0);
+
    Random rand2 = new Random(1);
+
    Random rand3 = new Random(1);
+

          
+
    Console.WriteLine("rand1 rand2 rand3");
+

          
+
    for (int i = 0; i < 15; i++)
+
    {
+
      Console.WriteLine("{0,-5} {1,-5} {2,-5}",
+
                        rand1.Next(0, 100),
+
                        rand2.Next(0, 100),
+
                        rand3.Next(0, 100));
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim rand1 As New Random(0)
+
    Dim rand2 As New Random(1)
+
    Dim rand3 As New Random(1)
+

          
+
    Console.WriteLine("rand1 rand2 rand3")
+

          
+
    For i As Integer = 1 To 15
+
      Console.WriteLine("{0,-5} {1,-5} {2,-5}", _
+
                        rand1.Next(0, 100), _
+
                        rand2.Next(0, 100), _
+
                        rand3.Next(0, 100))
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果の一例){{
+
rand1 rand2 rand3
+
92    36    36   
+
25    20    20   
+
99    95    95   
+
15    25    25   
+
12    90    90   
+
62    36    36   
+
78    75    75   
+
69    60    60   
+
81    83    83   
+
76    35    35   
+
88    85    85   
+
47    54    54   
+
8     64    64   
+
63    76    76   
+
30    67    67   
+
}}
+

          
+
Randomクラスのコンストラクタにシード値を指定しなかった場合は、システム時計の値(インスタンスを生成するときの&msdn(netfx,member,System.Environment.TickCount){Environment.TickCount};の値)が使用されます。
+

          
+
なお、Environment.TickCountの値は短時間に連続して取得すると同じ値が返される場合があります。 そのため、シード値を指定せず短時間に複数のRandomクラスのインスタンスを生成すると、同一のシード値からなるインスタンス(つまり同一の乱数系列)が生成される可能性がある点に注意が必要です。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Threading;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    // シード値を指定せずにインスタンスを生成
+
    Random rand1 = new Random();
+
    Random rand2 = new Random();
+

          
+
    Thread.Sleep(250); // 250ミリ秒待機
+

          
+
    Random rand3 = new Random();
+

          
+
    Console.WriteLine("rand1 rand2 rand3");
+

          
+
    for (int i = 0; i < 15; i++)
+
    {
+
      Console.WriteLine("{0,-5} {1,-5} {2,-5}",
+
                        rand1.Next(0, 100),
+
                        rand2.Next(0, 100),
+
                        rand3.Next(0, 100));
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Threading
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    ' シード値を指定せずにインスタンスを生成
+
    Dim rand1 As New Random()
+
    Dim rand2 As New Random()
+

          
+
    Thread.Sleep(250) ' 250ミリ秒待機
+

          
+
    Dim rand3 As New Random()
+

          
+

          
+
    Console.WriteLine("rand1 rand2 rand3")
+

          
+
    For i As Integer = 1 To 15
+
      Console.WriteLine("{0,-5} {1,-5} {2,-5}", _
+
                        rand1.Next(0, 100), _
+
                        rand2.Next(0, 100), _
+
                        rand3.Next(0, 100))
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果の一例){{
+
rand1 rand2 rand3
+
51    51    55   
+
78    78    55   
+
88    88    36   
+
62    62    2    
+
18    18    36   
+
6     6     37   
+
35    35    91   
+
25    25    13   
+
66    66    67   
+
47    47    28   
+
42    42    1    
+
23    23    79   
+
4     4     53   
+
4     4     14   
+
48    48    70   
+
}}
+

          
+
**乱数アルゴリズムの実装
+
擬似乱数の生成アルゴリズムにはいくつか種類がありますが、Randomクラスを継承して独自に疑似乱数を実装することもできます。 Randomクラスを継承する際に必要なのは、&msdn(netfx,member,System.Random.Sample){Sampleメソッド};をオーバーライドし、このメソッドで0.0以上1.0未満の乱数を返すように実装することです。
+

          
+
以下の例では、線形合同法を実装したLCGRandomクラスを作成し、Randomクラスが生成する乱数との比較を行っています。 なお、この実装は一つの例として挙げたもので、生成される乱数の周期や分散については考慮していません。 実際に使用する場合は注意してください。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
// 線形合同法による疑似乱数の生成を実装したクラス
+
class LCGRandom : Random
+
{
+
  private long x;
+
  private const long a = 1140671485;
+
  private const long c = 12820163;
+

          
+
  public LCGRandom()
+
    : this(Environment.TickCount)
+
  {
+
  }
+

          
+
  public LCGRandom(int seed)
+
  {
+
    x = seed;
+
  }
+

          
+
  protected override double Sample()
+
  {
+
    x = unchecked(a * x + c) & long.MaxValue;
+

          
+
    return (double)x / long.MaxValue;
+
  }
+
}
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Random rand = new Random(0);
+
    Random lcg  = new LCGRandom(0);
+

          
+
    Console.WriteLine("Random LCGRandom");
+

          
+
    for (int i = 0; i < 15; i++)
+
    {
+
      Console.WriteLine("{0,-7} {1,-7}",
+
                        rand.Next(0, 100),
+
                        lcg.Next(0, 100));
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
以下のコードでは、Sampleメソッドでオーバーフローが発生するため、/removeintchecks+をつけてコンパイルしないと動作が停止します。
+

          
+
#code(vb){{
+
' vbc /removeintchecks+
+
Imports System
+

          
+
' 線形合同法による疑似乱数の生成を実装したクラス
+
Class LCGRandom
+
  Inherits Random
+

          
+
  Private x As Long
+
  Private Const a As Long = 1140671485
+
  Private Const c As Long = 12820163
+

          
+
  Public Sub New()
+
    Me.New(Environment.TickCount)
+
  End Sub
+

          
+
  Public Sub New(ByVal seed As Integer)
+
    x = seed
+
  End Sub
+

          
+
  Protected Overrides Function Sample() As Double
+
    x = (a * x + c) And Long.MaxValue
+

          
+
    Return CDbl(x) / Long.MaxValue
+
  End Function
+
End Class
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim rand As New Random(0)
+
    Dim lcg As New LCGRandom(0)
+

          
+
    Console.WriteLine("Random LCGRandom")
+

          
+
    For i As Integer = 1 To 15
+
      Console.WriteLine("{0,-7} {1,-7}", _
+
                        rand.Next(0, 100), _
+
                        lcg.Next(0, 100))
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Random LCGRandom
+
92      0      
+
25      0      
+
99      97     
+
15      2      
+
12      65     
+
62      93     
+
78      23     
+
69      65     
+
81      44     
+
76      61     
+
88      37     
+
47      18     
+
8       78     
+
63      82     
+
30      28     
+
}}
+

          
+
Sampleメソッドをオーバーライドすることで独自の乱数生成を行えるほか、適切に実装することでメソッドの戻り値の範囲が閉区間となるようにすることもできます。 なお、引数をとらないNextメソッドなど、Sample以外のメソッドもオーバーライドしないと動作が変わらないメソッドがあります。 詳しくは&msdn(netfx,member,System.Random.Sample){Sampleメソッドのリファレンス};を参照してください。
+

          
+
*RandomNumberGeneratorクラス
+
Randomクラスの疑似乱数は、既知の乱数生成アルゴリズムに基づいています。 そのためRandomクラスが生成する疑似乱数は、次に生成される乱数が予測でき、暗号化などに用いる乱数としては問題となる場合があります。 そこで、このような疑似乱数の代わりとして、予測できない/しにくい乱数を生成する&msdn(netfx,type,System.Security.Cryptography.RandomNumberGenerator){RandomNumberGeneratorクラス};を用いることができます。
+

          
+
**乱数の取得
+
Randomクラスと同様、乱数を生成するためにはRandomNumberGeneratorクラスのインスタンスを作成する必要があります。 インスタンスを作成するには、&msdn(netfx,member,System.Security.Cryptography.RandomNumberGenerator.Create){Createメソッド};を使います。 作成したインスタンスを使って乱数を取得するには、&msdn(netfx,member,System.Security.Cryptography.RandomNumberGenerator.GetBytes){GetBytesメソッド};を使います。 GetBytesメソッドの使い方・動作はRandom.NextBytesメソッドと同様です。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Security.Cryptography;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    RandomNumberGenerator rng = RandomNumberGenerator.Create();
+

          
+
    byte[] nonce = new byte[16];
+

          
+
    for (int i = 0; i < 3; i++)
+
    {
+
      rng.GetBytes(nonce);
+

          
+
      Console.WriteLine(BitConverter.ToString(nonce));
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Security.Cryptography
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim rng As RandomNumberGenerator = RandomNumberGenerator.Create()
+

          
+
    Dim nonce(15) As Byte
+

          
+
    For i As Integer = 1 To 3
+
      rng.GetBytes(nonce)
+

          
+
      Console.WriteLine(BitConverter.ToString(nonce))
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果の一例){{
+
44-55-FB-46-91-80-CB-8E-EC-52-5A-06-48-13-46-B5
+
F7-30-40-46-6E-1B-80-00-B5-61-D5-13-0D-3A-BD-9E
+
5C-A6-2D-70-FF-55-BA-BF-E5-A1-D1-F8-94-1D-55-A6
+
}}
+

          
+
Randomクラスとは異なりシード値を指定しなくても、実行する度に毎回異なる乱数を得ることができます。
+

          
+
生成される乱数に0が含まれないようにしたい場合は、&msdn(netfx,member,System.Security.Cryptography.RandomNumberGenerator.GetNonZeroBytes){GetNonZeroBytesメソッド};を使うことができます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Security.Cryptography;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    RandomNumberGenerator rng = RandomNumberGenerator.Create();
+

          
+
    byte[] nonce = new byte[16];
+

          
+
    rng.GetNonZeroBytes(nonce);
+

          
+
    Console.WriteLine(BitConverter.ToString(nonce));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Security.Cryptography
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim rng As RandomNumberGenerator = RandomNumberGenerator.Create()
+

          
+
    Dim nonce(15) As Byte
+

          
+
    rng.GetNonZeroBytes(nonce)
+

          
+
    Console.WriteLine(BitConverter.ToString(nonce))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
Randomクラスとは異なり、NextやNextDoubleなどのメソッドは用意されていません。 そのため、Int32等の乱数が必要な場合は、生成された乱数を含むバイト列から変換する必要があります。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Security.Cryptography;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    RandomNumberGenerator rng = RandomNumberGenerator.Create();
+

          
+
    byte[] rand = new byte[4];
+

          
+
    for (int i = 0; i < 20; i++)
+
    {
+
      rng.GetBytes(rand);
+

          
+
      // 1から6までの整数に変換
+
      int val = 1 + (int)(6.0 * (BitConverter.ToUInt32(rand, 0) / ((double)uint.MaxValue + 1.0)));
+

          
+
      Console.Write("{0} ", val);
+
    }
+

          
+
    Console.WriteLine();
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Security.Cryptography
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim rng As RandomNumberGenerator = RandomNumberGenerator.Create()
+

          
+
    Dim rand(3) As Byte
+

          
+
    For i As Integer = 1 To 20
+
      rng.GetBytes(rand)
+

          
+
      ' 1から6までの整数に変換
+
      Dim val As Integer = 1 + CInt(Math.Truncate(6.0 * BitConverter.ToUInt32(rand, 0) / (UInteger.MaxValue + 1.0)))
+

          
+
      Console.Write("{0} ", val)
+
    Next
+

          
+
    Console.WriteLine()
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果の一例){{
+
4 4 1 5 1 1 3 1 2 2 3 2 4 2 1 3 1 3 5 6
+
}}
+

          
+
**RNGCryptoServiceProviderクラス
+
RandomNumberGeneratorクラスは抽象クラスで、Createメソッドで作成される実際のインスタンスは&msdn(netfx,type,System.Security.Cryptography.RNGCryptoServiceProvider){RNGCryptoServiceProviderクラス};です。
+

          
+
Createメソッドの引数で生成する暗号乱数ジェネレータの名前を指定することもできるようになっていますが、デフォルトの状態ではRNGCryptoServiceProvider以外に生成できるジェネレータは用意されていないようです。
+

          
+
また、特にCreateメソッドを使わなくても、直接RNGCryptoServiceProviderクラスのインスタンスを作成することもできます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Security.Cryptography;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
+

          
+
    byte[] nonce = new byte[16];
+

          
+
    rng.GetBytes(nonce);
+

          
+
    Console.WriteLine(BitConverter.ToString(nonce));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Security.Cryptography
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim rng As New RNGCryptoServiceProvider()
+

          
+
    Dim nonce(15) As Byte
+

          
+
    rng.GetBytes(nonce)
+

          
+
    Console.WriteLine(BitConverter.ToString(nonce))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
.NET Framework 4.0以降では、RandomNumberGeneratorクラスはIDisposableインターフェイスを実装しているので、Dispose()を明示的に呼び出したり、usingステートメントとともに使うことができます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Security.Cryptography;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
+
    {
+
      byte[] nonce = new byte[16];
+

          
+
      rng.GetBytes(nonce);
+

          
+
      Console.WriteLine(BitConverter.ToString(nonce));
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Security.Cryptography
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Using rng As New RNGCryptoServiceProvider()
+
      Dim nonce(15) As Byte
+

          
+
      rng.GetBytes(nonce)
+

          
+
      Console.WriteLine(BitConverter.ToString(nonce))
+
    End Using
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
なお、.NET Frameworkで実装されているRNGCryptoServiceProviderクラスは、
+
>暗号化サービス プロバイダー (CSP: Cryptographic Service Provider) によって提供された実装を使用して、暗号乱数ジェネレーター (RNG: Random Number Generator) を実装します。
+
とされているため、乱数の取得に&msdn(netfx,id,aa379942){CryptGenRandom関数};を使っていると思われます。 Monoの実装では、/dev/random, /dev/urandomもしくはWindows上ではCryptGenRandom関数を使用しているようです。
+

          
+
-参考
+
--[[MSC30-C. 疑似乱数の生成に rand() 関数を使用しない:http://www.jpcert.or.jp/sc-rules/c-msc30-c.html]]
+
--[[mono での NewGuid と RngCryptoServiceProvider - やこ~ん SuperNova2:http://d.hatena.ne.jp/saiya_moebius/20090319/1237419298]]
+
--[[/dev/random - Wikipedia:http://ja.wikipedia.org/wiki//dev/random]]
+

          
+
*Guid構造体
+
Guid構造体自体は乱数ジェネレータではありませんが、&msdn(netfx,member,System.Guid.NewGuid){NewGuidメソッド};は一意なGUIDを返すために乱数を使用しているため、このメソッドの戻り値は一種の乱数とみることもできます。 ただ、Guid構造体を乱数として用いる場合は、variantフィールドやバージョン番号などの一部のビットは常に同じ値となる点に注意が必要です。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    for (int i = 0; i < 10; i++)
+
    {
+
      Console.WriteLine(Guid.NewGuid());
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    For i As Integer = 1 To 10
+
      Console.WriteLine(Guid.NewGuid())
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果の一例){{
+
5c7932c9-448f-4d75-83b5-67c16ca95ea2
+
04e56298-75e3-45c8-8403-1ae5fdfb139a
+
d40b25f4-a912-422a-a071-d3a0bd322050
+
8d5e9c02-7ccd-4f2d-8565-3123f1acdc1a
+
4abc0ff5-fcce-4522-815f-e6e89799f138
+
93ccf3ff-2335-48f3-82c6-32b0ecd3c4a0
+
dc452781-0c44-4aca-b3ba-72f01a4c60e8
+
ebf44e59-014c-4acf-a9d4-e4fb60d237ad
+
2a36e0ae-283c-4a12-b204-310c4fede199
+
e3288df5-a942-4a77-8bf5-b3c5acc81b1a
+
}}
+

          
+
この結果にも現れているとおり、xxxxxxxx-xxxx-4xxx-8xxx-xxxxxxxxxxxxのビットは常に同じ値となります。
+

          
+
#navi(..)
+

          

programming/netfx/mathematics/2_biginteger/index.wiki.txt

current previous
1,681 0,0
+
${smdncms:title,BigInteger構造体}
+
${smdncms:header_title,BigInteger構造体 (System.Numerics)}
+
${smdncms:keywords,BigInteger,System.Numerics,長大,整数}
+
${smdncms:document_versions,codelang=cs,codelang=vb}
+

          
+
#navi(..)
+

          
+
&msdn(netfx,type,System.Numerics.BigInteger){BigInteger構造体};は.NET Framework 4より使用できるようになった構造体で、長大な整数を扱うのに便利な型です。 BigIntegerでは扱う値の大きさに合わせて格納領域の割り当てが行われるために扱える値に理論上の上限がなく、Int64やDecimalでは扱えないサイズの整数を扱うことができるようになっています。
+

          
+
なお、BigInteger構造体はアセンブリSystem.Numerics.dllに含まれています。 使用する場合は、System.Numerics.dllへの参照を追加する必要があります。
+

          
+
#googleadunit(banner)
+

          
+
*BigIntegerを使った例
+
次の例では、Int64とBigIntegerを使って1から30までの階乗を表示しています。 Int64では21!以上の値はオーバーフローするため正しくない結果が表示されていますが、BigIntegerでは正しい値が表示されています。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    long lfact = 1L;
+
    BigInteger bifact = 1;
+

          
+
    for (int i = 1; i <= 30; i++)
+
    {
+
      lfact *= i;
+
      bifact *= i;
+

          
+
      Console.WriteLine("{0,2}! = {1,-30} {2,-20}", i, lfact, bifact);
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
' vbc /removeintchecks+
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim lfact As Long = 1L
+
    DIm bifact As BigInteger = 1
+

          
+
    For i As Integer = 1 To 30
+
      lfact *= i
+
      bifact *= i
+

          
+
      Console.WriteLine("{0,2}! = {1,-30} {2,-20}", i, lfact, bifact)
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
 1! = 1                              1                   
+
 2! = 2                              2                   
+
 3! = 6                              6                   
+
 4! = 24                             24                  
+
 5! = 120                            120                 
+
 6! = 720                            720                 
+
 7! = 5040                           5040                
+
 8! = 40320                          40320               
+
 9! = 362880                         362880              
+
10! = 3628800                        3628800             
+
11! = 39916800                       39916800            
+
12! = 479001600                      479001600           
+
13! = 6227020800                     6227020800          
+
14! = 87178291200                    87178291200         
+
15! = 1307674368000                  1307674368000       
+
16! = 20922789888000                 20922789888000      
+
17! = 355687428096000                355687428096000     
+
18! = 6402373705728000               6402373705728000    
+
19! = 121645100408832000             121645100408832000  
+
20! = 2432902008176640000            2432902008176640000 
+
21! = -4249290049419214848           51090942171709440000
+
22! = -1250660718674968576           1124000727777607680000
+
23! = 8128291617894825984            25852016738884976640000
+
24! = -7835185981329244160           620448401733239439360000
+
25! = 7034535277573963776            15511210043330985984000000
+
26! = -1569523520172457984           403291461126605635584000000
+
27! = -5483646897237262336           10888869450418352160768000000
+
28! = -5968160532966932480           304888344611713860501504000000
+
29! = -7055958792655077376           8841761993739701954543616000000
+
30! = -8764578968847253504           265252859812191058636308480000000
+
}}
+

          
+
*演算子
+
BigIntegerには、四則演算・ビット演算・比較演算などの各種演算子が定義されているため、プリミティブな整数型と同じように演算式を記述することができます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    BigInteger x = ulong.MaxValue;
+
    BigInteger y = long.MaxValue;
+

          
+
    Console.WriteLine("{0} + {1} = {2}", x, y, x + y);
+
    Console.WriteLine("{0} - {1} = {2}", x, y, x - y);
+
    Console.WriteLine("{0} * {1} = {2}", x, y, x * y);
+
    Console.WriteLine("{0} / {1} = {2:D4}", x, y, x / y);
+
    Console.WriteLine("{0} % {1} = {2:D2}", x, y, x % y);
+
    Console.WriteLine("{0:X} >> 3 = {1:X}", x, x >> 3);
+
    Console.WriteLine("{0:X} << 3 = {1:X}", y, y << 3);
+
    Console.WriteLine("{0:X} ^ 0xffff0000 = {1:X}", x, x ^ 0xffff0000);
+

          
+
    if (x == y)
+
      Console.WriteLine("x == y");
+
    else
+
      Console.WriteLine("x != y");
+

          
+
    if (x < int.MaxValue)
+
      Console.WriteLine("x < int.MaxValue");
+
    else
+
      Console.WriteLine("x >= int.MaxValue");
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim x As BigInteger = ULong.MaxValue
+
    Dim y As BigInteger = Long.MaxValue
+

          
+
    Console.WriteLine("{0} + {1} = {2}", x, y, x + y)
+
    Console.WriteLine("{0} - {1} = {2}", x, y, x - y)
+
    Console.WriteLine("{0} * {1} = {2}", x, y, x * y)
+
    Console.WriteLine("{0} / {1} = {2:D4}", x, y, x / y)
+
    Console.WriteLine("{0} % {1} = {2:D2}", x, y, x Mod y)
+
    Console.WriteLine("{0:X} >> 3 = {1:X}", x, x >> 3)
+
    Console.WriteLine("{0:X} << 3 = {1:X}", y, y << 3)
+
    Console.WriteLine("{0:X} ^ 0xffff0000 = {1:X}", x, x Xor &hFFFF0000)
+

          
+
    If x = y Then
+
      Console.WriteLine("x = y")
+
    Else
+
      Console.WriteLine("x <> y")
+
    End If
+

          
+
    If x < Integer.MaxValue Then
+
      Console.WriteLine("x < Integer.MaxValue")
+
    Else
+
      Console.WriteLine("x >= Integer.MaxValue")
+
    End If
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
18446744073709551615 + 9223372036854775807 = 27670116110564327422
+
18446744073709551615 - 9223372036854775807 = 9223372036854775808
+
18446744073709551615 * 9223372036854775807 = 170141183460469231704017187605319778305
+
18446744073709551615 / 9223372036854775807 = 0002
+
18446744073709551615 % 9223372036854775807 = 01
+
0FFFFFFFFFFFFFFFF >> 3 = 1FFFFFFFFFFFFFFF
+
7FFFFFFFFFFFFFFF << 3 = 3FFFFFFFFFFFFFFF8
+
0FFFFFFFFFFFFFFFF ^ 0xffff0000 = 0FFFFFFFF0000FFFF
+
x != y
+
x >= int.MaxValue
+
}}
+

          
+
上記の結果からもわかるとおり、BigIntegerでもDやXなどの書式指定子がサポートされています。 なお、各演算子の代替メソッドも静的メソッドとして用意されています。
+

          
+
また、IComparable<BigInteger>, IEquatable<BigInteger>も実装しているので、このインターフェースを使用した比較も行えます。
+
-IComparable、IEquatableについての解説
+
--[[programming/netfx/comparison]]
+
--[[programming/netfx/comparison/0_comparison]]
+
--[[programming/netfx/comparison/1_equation]]
+

          
+
*型変換
+
BigIntegerでは、Int32などの整数型から/への型変換を行えるようになっています。 整数型へ変換する際、値が型の値域を越えている場合はOverflowExceptionがスローされます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    BigInteger bi = 3;
+

          
+
    int i = (int)bi;
+

          
+
    Console.WriteLine(i);
+

          
+
    bi = long.MaxValue;
+

          
+
    i = (int)bi;
+

          
+
    Console.WriteLine(i);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim bi As BigInteger = 3
+

          
+
    Dim i As Integer = CInt(bi)
+

          
+
    Console.WriteLine(i)
+

          
+
    bi = Long.MaxValue
+

          
+
    i = CInt(bi)
+

          
+
    Console.WriteLine(i)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
3
+

          
+
ハンドルされていない例外: System.OverflowException: Int32 型の値が大きすぎるか、または小さすぎます。
+
   場所 System.Numerics.BigInteger.op_Explicit(BigInteger value)
+
   場所 Sample.Main()
+
}}
+

          
+
また、DoubleやDecimalなどの実数型からの/への変換も同様に行えます。 実数型からBigIntegerに型変換する場合、小数部は切り捨てられます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    BigInteger bi;
+

          
+
    bi = (BigInteger)decimal.MaxValue;
+

          
+
    Console.WriteLine("{0} => {1}", decimal.MaxValue, bi);
+

          
+
    bi = (BigInteger)double.MaxValue;
+

          
+
    Console.WriteLine("{0} => {1}", double.MaxValue, bi);
+

          
+
    bi = (BigInteger)0.5;
+

          
+
    Console.WriteLine("{0} => {1}", 0.5, bi);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim bi As BigInteger
+

          
+
    bi = CType(Decimal.MaxValue, BigInteger)
+

          
+
    Console.WriteLine("{0} => {1}", Decimal.MaxValue, bi)
+

          
+
    bi = CType(Double.MaxValue, BigInteger)
+

          
+
    Console.WriteLine("{0} => {1}", Double.MaxValue, bi)
+

          
+
    bi = CType(0.5, BigInteger)
+

          
+
    Console.WriteLine("{0} => {1}", 0.5, bi)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
79228162514264337593543950335 => 79228162514264337593543950335
+
1.79769313486232E+308 => 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
+
0.5 => 0
+
}}
+

          
+
Int32, Double, Decimalなどを引数にとるコンストラクタも用意されているので、これを使うこともできます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Console.WriteLine(new BigInteger(int.MaxValue));
+
    Console.WriteLine(new BigInteger(long.MaxValue));
+
    Console.WriteLine(new BigInteger(float.MaxValue));
+
    Console.WriteLine(new BigInteger(double.MaxValue));
+
    Console.WriteLine(new BigInteger(decimal.MaxValue));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Console.WriteLine(New BigInteger(Integer.MaxValue))
+
    Console.WriteLine(New BigInteger(Long.MaxValue))
+
    Console.WriteLine(New BigInteger(Single.MaxValue))
+
    Console.WriteLine(New BigInteger(Double.MaxValue))
+
    Console.WriteLine(New BigInteger(Decimal.MaxValue))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
2147483647
+
9223372036854775807
+
340282346638528859811704183484516925440
+
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
+
79228162514264337593543950335
+
}}
+

          
+
&msdn(netfx,member,System.Numerics.BigInteger.Parse){Parseメソッド};、&msdn(netfx,member,System.Numerics.BigInteger.TryParse){TryParseメソッド};も用意されているので、文字列からBigIntegerを生成することもできます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Console.Write("x? ");
+

          
+
    BigInteger x = BigInteger.Parse(Console.ReadLine());
+

          
+
    Console.Write("y? ");
+

          
+
    BigInteger y = BigInteger.Parse(Console.ReadLine());
+

          
+
    Console.WriteLine("x * y = {0}", x * y);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Console.Write("x? ")
+

          
+
    Dim x As BigInteger = BigInteger.Parse(Console.ReadLine())
+

          
+
    Console.Write("y? ")
+

          
+
    Dim y As BigInteger = BigInteger.Parse(Console.ReadLine())
+

          
+
    Console.WriteLine("x * y = {0}", x * y)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
x? 10000000000000000000000000000000000000000000000
+
y? 654654654654987984321324168621357987
+
x * y = 6546546546549879843213241686213579870000000000000000000000000000000000000000000000
+
}}
+

          
+
BigIntegerをバイト配列に変換するには、&msdn(netfx,member,System.Numerics.BigInteger.ToByteArray){ToByteArrayメソッド};を使うことができます。 得られるバイト配列はリトルエンディアンになります。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    BigInteger a = 1;
+
    BigInteger b = -1;
+
    BigInteger c = 256;
+
    BigInteger d = -256;
+
    BigInteger e = 0x12345678;
+

          
+
    Console.WriteLine(BitConverter.ToString(a.ToByteArray()));
+
    Console.WriteLine(BitConverter.ToString(b.ToByteArray()));
+
    Console.WriteLine(BitConverter.ToString(c.ToByteArray()));
+
    Console.WriteLine(BitConverter.ToString(d.ToByteArray()));
+
    Console.WriteLine(BitConverter.ToString(e.ToByteArray()));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim a As BigInteger = 1
+
    Dim b As BigInteger = -1
+
    Dim c As BigInteger = 256
+
    Dim d As BigInteger = -256
+
    Dim e As BigInteger = &h12345678
+

          
+
    Console.WriteLine(BitConverter.ToString(a.ToByteArray()))
+
    Console.WriteLine(BitConverter.ToString(b.ToByteArray()))
+
    Console.WriteLine(BitConverter.ToString(c.ToByteArray()))
+
    Console.WriteLine(BitConverter.ToString(d.ToByteArray()))
+
    Console.WriteLine(BitConverter.ToString(e.ToByteArray()))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
01
+
FF
+
00-01
+
00-FF
+
78-56-34-12
+
}}
+

          
+
また、BigIntegerのコンストラクタはバイト配列を引数にとるバージョンが用意されているので、バイト配列からBigIntegerを構築することもできます。
+

          
+
*値の種類
+
BigIntegerには、格納されている値の種類を知るための次のようなプロパティが用意されています。
+
:&msdn(netfx,member,System.Numerics.BigInteger.IsZero){IsZero};|値が0かどうか。
+
:&msdn(netfx,member,System.Numerics.BigInteger.IsOne){IsOne};|値が1かどうか。
+
:&msdn(netfx,member,System.Numerics.BigInteger.IsEven){IsEven};|値が偶数かどうか。
+
:&msdn(netfx,member,System.Numerics.BigInteger.IsPowerOfTwo){IsPowerOfTwo};|値が2の累乗かどうか。
+
:&msdn(netfx,member,System.Numerics.BigInteger.Sign){Sign};|値の符号を取得する。 返される値はInt32で、正なら1、負なら-1、0なら0が返される(&msdn(netfx,member,System.Math.Sing){Math.Signメソッド};と同様の動作)
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    BigInteger bi = 1;
+

          
+
    Console.WriteLine(bi);
+
    Console.WriteLine("IsZero       : {0}", bi.IsZero);
+
    Console.WriteLine("IsOne        : {0}", bi.IsOne);
+
    Console.WriteLine("IsEven       : {0}", bi.IsEven);
+
    Console.WriteLine("IsPowerOfTwo : {0}", bi.IsPowerOfTwo);
+
    Console.WriteLine("Sign         : {0}", bi.Sign);
+
    Console.WriteLine();
+

          
+
    bi = -4;
+

          
+
    Console.WriteLine(bi);
+
    Console.WriteLine("IsZero       : {0}", bi.IsZero);
+
    Console.WriteLine("IsOne        : {0}", bi.IsOne);
+
    Console.WriteLine("IsEven       : {0}", bi.IsEven);
+
    Console.WriteLine("IsPowerOfTwo : {0}", bi.IsPowerOfTwo);
+
    Console.WriteLine("Sign         : {0}", bi.Sign);
+
    Console.WriteLine();
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim bi As BigInteger = 1
+

          
+
    Console.WriteLine(bi)
+
    Console.WriteLine("IsZero       : {0}", bi.IsZero)
+
    Console.WriteLine("IsOne        : {0}", bi.IsOne)
+
    Console.WriteLine("IsEven       : {0}", bi.IsEven)
+
    Console.WriteLine("IsPowerOfTwo : {0}", bi.IsPowerOfTwo)
+
    Console.WriteLine("Sign         : {0}", bi.Sign)
+
    Console.WriteLine()
+

          
+
    bi = -4
+

          
+
    Console.WriteLine(bi)
+
    Console.WriteLine("IsZero       : {0}", bi.IsZero)
+
    Console.WriteLine("IsOne        : {0}", bi.IsOne)
+
    Console.WriteLine("IsEven       : {0}", bi.IsEven)
+
    Console.WriteLine("IsPowerOfTwo : {0}", bi.IsPowerOfTwo)
+
    Console.WriteLine("Sign         : {0}", bi.Sign)
+
    Console.WriteLine()
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
1
+
IsZero       : False
+
IsOne        : True
+
IsEven       : False
+
IsPowerOfTwo : True
+
Sign         : 1
+

          
+
-4
+
IsZero       : False
+
IsOne        : False
+
IsEven       : True
+
IsPowerOfTwo : False
+
Sign         : -1
+

          
+
}}
+

          
+
なお、0、+1、-1の三値は静的プロパティとして用意されています。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Console.WriteLine(BigInteger.Zero);
+
    Console.WriteLine(BigInteger.One);
+
    Console.WriteLine(BigInteger.MinusOne);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Console.WriteLine(BigInteger.Zero)
+
    Console.WriteLine(BigInteger.One)
+
    Console.WriteLine(BigInteger.MinusOne)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
0
+
1
+
-1
+
}}
+

          
+
*数学関数
+
[[Mathクラス>programming/netfx/mathematics/0_math]]に用意されている数学関数は、BigIntegerをサポートしていません。 代わりに、これらの関数はBigInteger構造体のメソッドとして提供されています。 BigIntegerには次のようなメソッドが用意されています。 Mathクラスと同様、いずれも静的メソッドです。
+

          
+
|*BigIntegerに用意されている数学関数とそれに相当するMathクラスのメソッド
+
|~関数|~BigIntegerのメソッド|~相当するMathクラスのメソッド|h
+
|絶対値 &#x7c;&italic{x};&#x7c;|&msdn(netfx,member,System.Numerics.BigInteger.Abs){BigInteger.Abs};(x)|[[Math.Abs>programming/netfx/mathematics/0_math#FuncAbsSign]]|
+
|最大 max(&italic{x};, &italic{y};)|&msdn(netfx,member,System.Numerics.BigInteger.Max){BigInteger.Max};(x, y)|[[Math.Max>programming/netfx/mathematics/0_math#FuncMinMax]]|
+
|最小 min(&italic{x};, &italic{y};)|&msdn(netfx,member,System.Numerics.BigInteger.Min){BigInteger.Min};(x, y)|[[Math.Min>programming/netfx/mathematics/0_math#FuncMinMax]]|
+
|商と剰余|&msdn(netfx,member,System.Numerics.BigInteger.DivRem){BigInteger.DivRem};(x, y, out remainder)|[[Math.DivRem>programming/netfx/mathematics/0_math#FuncMulDiv]]|
+
|累乗 &italic{x};&sup{&italic{n};};|&msdn(netfx,member,System.Numerics.BigInteger.Pow){BigInteger.Pow};(x, n)|[[Math.Pow>programming/netfx/mathematics/0_math#FuncPower]]|
+
|自然対数 ln &italic{x};|&msdn(netfx,member,System.Numerics.BigInteger.Log){BigInteger.Log};(x)|[[Math.Log>programming/netfx/mathematics/0_math#FuncLogarithmic]]|
+
|常用対数 log&sub{10}; &italic{x};|&msdn(netfx,member,System.Numerics.BigInteger.Log10){BigInteger.Log10};(x)|[[Math.Log10>programming/netfx/mathematics/0_math#FuncLogarithmic]]|
+
|対数 log&sub{a}; &italic{x};|&msdn(netfx,member,System.Numerics.BigInteger.Log){BigInteger.Log};(x, a)|[[Math.Log>programming/netfx/mathematics/0_math#FuncLogarithmic]]|
+
|~関数|~BigIntegerのメソッド|~相当するMathクラスのメソッド|f
+

          
+
次の例では、BigIntegerを使って5以上の階乗の値を求め、BigInteger.Log10メソッドでの桁数を求めて指数表記で表示しています。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    BigInteger fact = BigInteger.One;
+

          
+
    for (int i = 1; i <= 30; i++)
+
    {
+
      fact *= i;
+

          
+
      if (i < 5)
+
        continue;
+

          
+
      int exp = (int)BigInteger.Log10(fact);
+
      double mant = (double)fact / Math.Pow(10, exp);
+

          
+
      Console.WriteLine("{0,2}! = {1,35} ≒ {2:F2} x 10^{3}", i, fact, mant, exp);
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim fact As BigInteger = BigInteger.One
+

          
+
    For i As Integer = 1 To 30
+
      fact *= i
+

          
+
      If i < 5 Then Continue For
+

          
+
      Dim exp As Integer = CInt(Math.Truncate(BigInteger.Log10(fact)))
+
      Dim mant As Double = CDbl(fact) / Math.Pow(10, exp)
+

          
+
      Console.WriteLine("{0,2}! = {1,35} ≒ {2:F2} x 10^{3}", i, fact, mant, exp)
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
 5! =                                 120 ≒ 1.20 x 10^2
+
 6! =                                 720 ≒ 7.20 x 10^2
+
 7! =                                5040 ≒ 5.04 x 10^3
+
 8! =                               40320 ≒ 4.03 x 10^4
+
 9! =                              362880 ≒ 3.63 x 10^5
+
10! =                             3628800 ≒ 3.63 x 10^6
+
11! =                            39916800 ≒ 3.99 x 10^7
+
12! =                           479001600 ≒ 4.79 x 10^8
+
13! =                          6227020800 ≒ 6.23 x 10^9
+
14! =                         87178291200 ≒ 8.72 x 10^10
+
15! =                       1307674368000 ≒ 1.31 x 10^12
+
16! =                      20922789888000 ≒ 2.09 x 10^13
+
17! =                     355687428096000 ≒ 3.56 x 10^14
+
18! =                    6402373705728000 ≒ 6.40 x 10^15
+
19! =                  121645100408832000 ≒ 1.22 x 10^17
+
20! =                 2432902008176640000 ≒ 2.43 x 10^18
+
21! =                51090942171709440000 ≒ 5.11 x 10^19
+
22! =              1124000727777607680000 ≒ 1.12 x 10^21
+
23! =             25852016738884976640000 ≒ 2.59 x 10^22
+
24! =            620448401733239439360000 ≒ 6.20 x 10^23
+
25! =          15511210043330985984000000 ≒ 1.55 x 10^25
+
26! =         403291461126605635584000000 ≒ 4.03 x 10^26
+
27! =       10888869450418352160768000000 ≒ 1.09 x 10^28
+
28! =      304888344611713860501504000000 ≒ 3.05 x 10^29
+
29! =     8841761993739701954543616000000 ≒ 8.84 x 10^30
+
30! =   265252859812191058636308480000000 ≒ 2.65 x 10^32
+
}}
+

          
+
また、Mathクラスでは提供されない、次のようなメソッドも用意されています。
+
:&msdn(netfx,member,System.Numerics.BigInteger.ModPow){BigInteger.ModPow};(value, exponent, modulus)|次の式で得られる剰余を求めます。 &italic{value};&sup{&italic{exponent};}; mod &italic{modulus};
+
:&msdn(netfx,member,System.Numerics.BigInteger.GreatestCommonDivisor){BigInteger.GreatestCommonDivisor};(x, y)|xとyの最大公約数を求めます。
+

          
+
一方で、java.math.BigIntegerにあるようなmodInverseやnextProbablePrimeなどのメソッドは用意されていません。
+

          
+
#navi(..)
+

          

programming/netfx/mathematics/index.wiki.txt

current previous
1,8 0,0
+
${smdncms:title,数学関数・高度な数値型}
+
${smdncms:keywords,}
+

          
+
.NET Frameworkでは、sinやabsなどの関数はMathクラスにまとめられています。 また、乱数を取り扱うクラスはRandomクラスとして用意されています。 ここではそれらのクラスで提供される関数と使い方について解説します。 また、.NET Framework 4より新たに導入されたSystem.Numerics名前空間の数値型(BigInteger構造体・Complex構造体)についても解説します。
+

          
+
-ページ一覧
+
#ls2_1(noroot,pathsort)
+

          

programming/netfx/mathematics/0_math/index.wiki.txt

current previous
1,986 0,0
+
${smdncms:title,数学関数}
+
${smdncms:header_title,数学関数 (System.Math)}
+
${smdncms:keywords,数学,関数,Math}
+
${smdncms:document_versions,codelang=cs,codelang=vb}
+

          
+
#navi(..)
+

          
+
&msdn(netfx,type,System.Math){Mathクラス};には、基本的な数学関数が用意されています。 これらはいずれもMathクラスの静的メソッドとして提供されます。 ここでは、Mathクラスのメソッドについて解説します。
+

          
+
#googleadunit(banner)
+

          
+
*メソッドと関数の対応
+
以下で解説するMathクラスに用意されているメソッドと、数学関数の対応を表にまとめると次のようになります。 個々のメソッドの詳細については順に解説していきます。
+

          
+
|*Mathクラスのメソッドと数学関数の対応
+
|~関数|~対応するMathクラスのメソッド|~解説へのリンク|h
+
|絶対値 &#x7c;&italic{x};&#x7c;|Math.Abs(x)|[[解説へ>#FuncAbsSign]]|
+
|符号関数 sgn &italic{x};|Math.Sign(x)|[[解説へ>#FuncAbsSign]]|
+
|最大 max(&italic{x};, &italic{y};)|Math.Max(x, y)|[[解説へ>#FuncMinMax]]|
+
|最小 min(&italic{x};, &italic{y};)|Math.Min(x, y)|[[解説へ>#FuncMinMax]]|
+
|天井関数 ⌈&italic{x};⌉|Math.Ceiling(x)|[[解説へ>#FuncRound]]|
+
|床関数 ⌊&italic{x};⌋|Math.Floor(x)|[[解説へ>#FuncRound]]|
+
|累乗 &italic{x};&sup{&italic{y};};|Math.Pow(x, y)|[[解説へ>#FuncPower]]|
+
|ネイピア数の累乗 &italic{e};&sup{&italic{x};};|Math.Exp(x)|[[解説へ>#FuncPower]]|
+
|平方根 √&italic{x};|Math.Sqrt(x)|[[解説へ>#FuncPower]]|
+
|累乗根 &sup{&italic{n};};√&italic{x};|Math.Pow(x, 1.0 / n)|[[解説へ>#FuncPower]]|
+
|自然対数 ln &italic{x};|Math.Log(x)|[[解説へ>#FuncLogarithmic]]|
+
|常用対数 log&sub{10}; &italic{x};|Math.Log10(x)|[[解説へ>#FuncLogarithmic]]|
+
|対数 log&sub{a}; &italic{x};|Math.Log(x, a)|[[解説へ>#FuncLogarithmic]]|
+
|三角関数 sin &italic{x};, cos &italic{x};, tan &italic{x};|Math.Sin(x), Math.Cos(x), Math.Tan(x)|[[解説へ>#FuncTrigonometric]]|
+
|逆三角関数 sin&sup{-1}; &italic{x};, cos&sup{-1}; &italic{x};, tan&sup{-1}; &italic{x};|Math.Asin(x), Math.Acos(x), Math.Atan(x)|[[解説へ>#FuncTrigonometric]]|
+
|双曲線関数 sinh &italic{x};, cosh &italic{x};, tanh &italic{x};|Math.Sinh(x), Math.Cosh(x), Math.Tanh(x)|[[解説へ>#FuncTrigonometric]]|
+
|~関数|~対応するMathクラスのメソッド|~解説へのリンク|f
+

          
+

          
+
*&aname(FuncAbsSign){絶対値・符号 (Abs, Sign)};
+
絶対値を求めるには&msdn(netfx,member,System.Math.Abs){Absメソッド};、値の符号(正負)を求めるには&msdn(netfx,member,System.Math.Sign){Signメソッド};を使用します。 Absメソッド・Signメソッドともに戻り値は引数と同じ型になります。 Signメソッドでは、引数の値が正の場合は+1、負の場合は-1、0の場合は0が返されます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  public 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));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public 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
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Abs(3) = 3
+
Abs(-5) = 5
+
Abs(-3.14) = 3.14
+
Sign(3) = 1
+
Sign(-3.14) = -1
+
Sign(0) = 0
+
}}
+

          
+
整数型の場合、AbsメソッドでMinValueと同じ値の絶対値を求めようとするとオーバーフローとなるためOverflowExceptionがスローされる点に注意が必要です。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  public static void Main()
+
  {
+
    try {
+
      Console.WriteLine(Math.Abs(int.MinValue));
+
    }
+
    catch (Exception ex) {
+
      Console.WriteLine(ex);
+
    }
+

          
+
    try {
+
      Console.WriteLine(Math.Abs(long.MinValue));
+
    }
+
    catch (Exception ex) {
+
      Console.WriteLine(ex);
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Try
+
      Console.WriteLine(Math.Abs(Integer.MinValue))
+
    Catch ex As Exception
+
      Console.WriteLine(ex)
+
    End Try
+

          
+
    Try
+
      Console.WriteLine(Math.Abs(Long.MinValue))
+
    Catch ex As Exception
+
      Console.WriteLine(ex)
+
    End Try
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
System.OverflowException: 2 の補数の最小値を無効にすることはできません。
+
   場所 System.Math.AbsHelper(Int32 value)
+
   場所 Sample.Main()
+
System.OverflowException: 2 の補数の最小値を無効にすることはできません。
+
   場所 System.Math.AbsHelper(Int64 value)
+
   場所 Sample.Main()
+
}}
+

          
+
また、Double型の場合、値が無限大でもSignメソッドは適切な符号を返しますが、NaNの場合はArithmeticExceptionをスローします。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  public 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));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public 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
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
1
+
-1
+

          
+
ハンドルされていない例外: System.ArithmeticException: 関数は浮動小数点の非数値を受け入れません。
+
   場所 System.Math.Sign(Double value)
+
   場所 Sample.Main()
+
}}
+

          
+
*&aname(FuncMinMax){最大・最小 (Min, Max)};
+
二つの値のうち大きい方を求めるには&msdn(netfx,member,System.Math.Max){Maxメソッド};、小さい方を求めるには&msdn(netfx,member,System.Math.Min){Minメソッド};を使用します。 Maxメソッド・Minメソッドも、戻り値は引数と同じ型になります。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  public 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();
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public 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
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
3
+
3
+
3.14
+

          
+
1
+
1
+
-1.23
+
}}
+

          
+
Maxメソッド・Minメソッドともに引数は2つしかとらないため、3つ以上の値から最大値・最小値を求めたい場合、複数回呼び出す必要があります。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  public 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)));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public 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
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
max = 5
+
min = 1
+
}}
+

          
+
なお、配列やコレクションなどから最大値・最小値を求める場合は、&msdn(netfx,member,System.Linq.Enumerable.Max){Enumerable.Maxメソッド};または&msdn(netfx,member,System.Linq.Enumerable.Min){Enumerable.Minメソッド};を使うこともできます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Linq;
+

          
+
class Sample
+
{
+
  public 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());
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Linq
+

          
+
Class Sample
+
  Public 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
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
max = 6
+
min = 1
+
}}
+

          
+
*&aname(FuncRound){実数の丸め・端数処理 (Truncate, Ceiling, Floor, Round)};
+
Double・Decimalの丸め・端数処理を行うには、次のメソッドを使用します。 各メソッドの動作は次のとおりです。
+

          
+
:&msdn(netfx,method,System.Math.Truncate){Truncate}; (切り捨て)|指定した数値の端数部分を切り捨てた整数(数直線上で0の方向にある次の整数)に丸められる。
+
:&msdn(netfx,method,System.Math.Ceiling){Ceiling}; (正の無限大への丸め)|指定した数値以下の最大の整数(数直線上で正の方向にある次の整数)に丸められる。
+
:&msdn(netfx,method,System.Math.Floor){Floor}; (負の無限大への丸め)|指定した数値以上の最小の整数(数直線上で負の方向にある次の整数)に丸められる。
+
:&msdn(netfx,method,System.Math.Round){Round};|丸めの方法&msdn(netfx,method,System.MidpointRounding){MidpointRounding};を指定して整数への丸めを行います。
+
::MidpointRounding.ToEven (最近接偶数への丸め、銀行家丸め)|数値の端数は偶数方向に丸められる。&br;Roundメソッドの呼び出しでMidpointRoundingを指定しなかった場合はこの動作となる。
+
::MidpointRounding.AwayFromZero (四捨五入)|数値の端数はゼロから遠い方に丸められる。
+

          
+
なお、C#での整数型へのキャストはTruncateによる切り捨て、VBでのCInt等による型変換はMidpointRounding.ToEvenを指定したRoundによる丸めと同じ動作となります。
+

          
+
これらのメソッドを呼び出した結果の違いは次のようになります。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Console.WriteLine("{0,6}| {1,12} {2,12} {3,12} {4,12} {5,12} {6,12}| {0,6}",
+
                      "value",
+
                      "Ceiling",
+
                      "Floor",
+
                      "Truncate",
+
                      "Round",
+
                      "ToEven",
+
                      "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,12:F2} {5,12:F2} {6,12:F2}| {0,6:F2}",
+
                        d,
+
                        Math.Ceiling(d),
+
                        Math.Floor(d),
+
                        Math.Truncate(d),
+
                        Math.Round(d),
+
                        Math.Round(d, MidpointRounding.ToEven),
+
                        Math.Round(d, MidpointRounding.AwayFromZero));
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Console.WriteLine("{0,6}| {1,12} {2,12} {3,12} {4,12} {5,12} {6,12}| {0,6}", _
+
                      "value", _
+
                      "Ceiling", _
+
                      "Floor", _
+
                      "Truncate", _
+
                      "Round", _
+
                      "ToEven", _
+
                      "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,12:F2} {5,12:F2} {6,12:F2}| {0,6:F2}", _
+
                        d, _
+
                        Math.Ceiling(d), _
+
                        Math.Floor(d), _
+
                        Math.Truncate(d), _
+
                        Math.Round(d), _
+
                        Math.Round(d, MidpointRounding.ToEven), _
+
                        Math.Round(d, MidpointRounding.AwayFromZero))
+
    Next
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
 value|      Ceiling        Floor     Truncate        Round       ToEven AwayFromZero|  value
+
--------------------------------------------------------------------------------------------------
+
  2.75|         3.00         2.00         2.00         3.00         3.00         3.00|   2.75
+
  2.50|         3.00         2.00         2.00         2.00         2.00         3.00|   2.50
+
  2.25|         3.00         2.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|   2.00
+
  1.75|         2.00         1.00         1.00         2.00         2.00         2.00|   1.75
+
  1.50|         2.00         1.00         1.00         2.00         2.00         2.00|   1.50
+
  1.25|         2.00         1.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|   1.00
+
  0.75|         1.00         0.00         0.00         1.00         1.00         1.00|   0.75
+
  0.50|         1.00         0.00         0.00         0.00         0.00         1.00|   0.50
+
  0.25|         1.00         0.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.00
+
 -0.25|         0.00        -1.00         0.00         0.00         0.00         0.00|  -0.25
+
 -0.50|         0.00        -1.00         0.00         0.00         0.00        -1.00|  -0.50
+
 -0.75|         0.00        -1.00         0.00        -1.00        -1.00        -1.00|  -0.75
+
 -1.00|        -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.00|  -1.25
+
 -1.50|        -1.00        -2.00        -1.00        -2.00        -2.00        -2.00|  -1.50
+
 -1.75|        -1.00        -2.00        -1.00        -2.00        -2.00        -2.00|  -1.75
+
 -2.00|        -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.00|  -2.25
+
 -2.50|        -2.00        -3.00        -2.00        -2.00        -2.00        -3.00|  -2.50
+
 -2.75|        -2.00        -3.00        -2.00        -3.00        -3.00        -3.00|  -2.75
+
}}
+

          
+
なお、Roundメソッドは戻り値に含まれる小数部分の桁数を指定できるため、丸めを行う際の桁を指定することが出来ます。 次の例は、桁を指定して四捨五入する例です。
+

          
+
#tabpage(C#)
+
#code(cs,桁を指定した四捨五入){{
+
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));
+

          
+
    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),
+
                        Math.Round(d, 1, MidpointRounding.AwayFromZero),
+
                        Math.Round(d, 2, MidpointRounding.AwayFromZero),
+
                        Math.Round(d, 3, MidpointRounding.AwayFromZero));
+
    }
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb,桁を指定した四捨五入){{
+
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))
+

          
+
    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
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
   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
+
}}
+

          
+
*&aname(FuncMulDiv){積・商と剰余 (BigMul, DivRem)};
+
オーバーフローを起こさずにint同士の積を求めたい場合、&msdn(netfx,method,System.Math.BigMul){BigMulメソッド};を用いることができます。 このメソッドは二つのintを引数にとり、それらの積をlong型で返します。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
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);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public 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
+
}}
+
#tabpage-end
+

          
+
#prompt(オーバーフローのチェックを有効にしている場合){{
+
2147483647 * 2 = 4294967294
+

          
+
ハンドルされていない例外: System.OverflowException: 算術演算の結果オーバーフローが発生しました。
+
   場所 Sample.Main()
+
}}
+

          
+
#prompt(オーバーフローのチェックを無効にしている場合){{
+
2147483647 * 2 = 4294967294
+
2147483647 * 2 = -2
+
}}
+

          
+
&msdn(netfx,method,System.Math.DivRem){DivRemメソッド};を用いると、整数同士の除算による商と剰余を同時に求めることができます。 商は戻り値として、剰余はoutパラメータとして返されます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    int a = 5;
+
    int b = 3;
+
    int div, rem;
+

          
+
    div = Math.DivRem(a, b, out rem);
+

          
+
    Console.WriteLine("{0}÷{1} = {2}…{3}", a, b, div, rem);
+

          
+
    div = a / b;
+
    rem = a % b;
+

          
+
    Console.WriteLine("{0}÷{1} = {2}…{3}", a, b, div, rem);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim a As Integer = 5
+
    Dim b As Integer = 3
+
    Dim div, rm As Integer
+

          
+
    div = Math.DivRem(a, b, rm)
+

          
+
    Console.WriteLine("{0}÷{1} = {2}…{3}", a, b, div, rm)
+

          
+
    div = a \ b
+
    rm  = a Mod b
+

          
+
    Console.WriteLine("{0}÷{1} = {2}…{3}", a, b, div, rm)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
5÷3 = 1…2
+
5÷3 = 1…2
+
}}
+

          
+

          
+
*&aname(FuncPower){累乗・平方根 (Pow, Sqrt)};
+
累乗(べき乗)を求めるには&msdn(netfx,member,System.Math.Pow){Powメソッド};、平方根を求めるには&msdn(netfx,member,System.Math.Sqrt){Sqrtメソッド};を使用します。 これらのメソッドは、引数・戻り値ともにDoubleです。 累乗根を求めるメソッドは用意されていませんが、Powメソッドに根の逆数(立方根なら⅓)を指定することで累乗根を求めることができます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Console.WriteLine("2^3 = {0}", Math.Pow(2, 3));
+
    Console.WriteLine("3^2 = {0}", Math.Pow(3, 2));
+

          
+
    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));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Console.WriteLine("2^3 = {0}", Math.Pow(2, 3))
+
    Console.WriteLine("3^2 = {0}", Math.Pow(3, 2))
+

          
+
    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
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
2^3 = 8
+
3^2 = 9
+
√2 = 1.4142135623731
+
√4 = 2
+
^3√8 = 2
+
}}
+

          
+
なお、VBには累乗演算子 ''^'' が用意されているので、これを用いて累乗・累乗根を求めることもできます。
+

          
+
#code(vb,累乗演算子を用いて累乗・累乗根を求める例){{
+
Imports System
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Console.WriteLine("2^3 = {0}", 2 ^ 3)
+
    Console.WriteLine("3^2 = {0}", 3 ^ 2)
+

          
+
    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
+
}}
+

          
+
一方で、Mathクラスにはユークリッド距離/直角三角形の斜辺の長さを求めるhypot関数のようなメソッドは用意されていないため、Powメソッド・Sqrtメソッドを組み合わせて計算する必要があります。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
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)));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public 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
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
hypot(3, 4) = 5
+
}}
+

          
+
ネイピア数&italic{e};の累乗を求めるには、&msdn(netfx,member,System.Math.Exp){Expメソッド};を使用することもできます。 なお、ネイピア数&italic{e};は&msdn(netfx,member,System.Math.E){Math.Eフィールド};を参照することで得られるので、わざわざ定数を定義する必要はありません。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Console.WriteLine(Math.Exp(1));
+
    Console.WriteLine(Math.Pow(Math.E, 1));
+
    Console.WriteLine();
+

          
+
    Console.WriteLine(Math.Exp(2));
+
    Console.WriteLine(Math.Pow(Math.E, 2));
+
    Console.WriteLine();
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Console.WriteLine(Math.Exp(1))
+
    Console.WriteLine(Math.Pow(Math.E, 1))
+
    Console.WriteLine()
+

          
+
    Console.WriteLine(Math.Exp(2))
+
    Console.WriteLine(Math.Pow(Math.E, 2))
+
    Console.WriteLine()
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
2.71828182845905
+
2.71828182845905
+

          
+
7.38905609893065
+
7.38905609893065
+

          
+
}}
+

          
+

          
+
*&aname(FuncLogarithmic){対数 (Log, Log10)};
+
対数を求めるには&msdn(netfx,member,System.Math.Log){Logメソッド};を使用します。 このメソッドは任意の底を指定することもできます。 log&sub{a};xを求めるには、Math.Log(x, a)として呼び出します。 底を指定しない場合は、ネイピア数&italic{e};を底とした自然対数lnとなります。 また、底を10とした常用対数log&sub{10};xを求めるには&msdn(netfx,member,System.Math.Log10){Log10メソッド};を使用することができます。 これらのメソッドは、いずれも引数・戻り値ともにDoubleです。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Console.WriteLine("ln(2.7182818)    = {0}", Math.Log(2.7182818));
+
    Console.WriteLine("log_e(2.7182818) = {0}", Math.Log(2.7182818, Math.E));
+
    Console.WriteLine();
+

          
+
    Console.WriteLine("log_10(2)   = {0}", Math.Log10(2));
+
    Console.WriteLine("log_10(100) = {0}", Math.Log(100, 10));
+
    Console.WriteLine();
+

          
+
    Console.WriteLine("log_2(2) = {0}", Math.Log(2, 2));
+
    Console.WriteLine("log_2(4) = {0}", Math.Log(4, 2));
+
    Console.WriteLine();
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Console.WriteLine("ln(2.7182818)    = {0}", Math.Log(2.7182818))
+
    Console.WriteLine("log_e(2.7182818) = {0}", Math.Log(2.7182818, Math.E))
+
    Console.WriteLine()
+

          
+
    Console.WriteLine("log_10(2)   = {0}", Math.Log10(2))
+
    Console.WriteLine("log_10(100) = {0}", Math.Log(100, 10))
+
    Console.WriteLine()
+

          
+
    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
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
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
+

          
+
}}
+

          
+

          
+
*&aname(FuncTrigonometric){三角関数・双曲線関数 (Sin, Cos, Tan, etc.)};
+
三角関数はそれぞれ&msdn(netfx,member,System.Math.Sin){Sinメソッド};、&msdn(netfx,member,System.Math.Cos){Cosメソッド};、&msdn(netfx,member,System.Math.Tan){Tanメソッド};として用意されています。 いずれも、角度の単位はラジアンです。 円周率πは&msdn(netfx,member,System.Math.PI){Math.PIフィールド};を参照することで得られるので、わざわざ定数を定義する必要はありません。 なお、度数法・弧度法の変換を行うメソッドは用意されていないので、必要に応じて変換処理を書く必要があります。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
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));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public 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
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Sin(π/6) = 0.5
+
Cos(π/4) = 0.707106781186548
+
Tan(π/3) = 1.73205080756888
+

          
+
Sin(45°) = 0.707106781186547
+
Cos(45°) = 0.707106781186548
+
Tan(45°) = 1
+
}}
+

          
+
逆三角関数はそれぞれ&msdn(netfx,member,System.Math.Asin){Asinメソッド};、&msdn(netfx,member,System.Math.Acos){Acosメソッド};、&msdn(netfx,member,System.Math.Atan){Atanメソッド};として用意されています。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
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));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public 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
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
Asin(0.5) = 0.523598775598299
+
Acos(0.7071) = 0.785407753397449
+
Atan(1.0) = 0.785398163397448
+
}}
+

          
+
座標変換などでよく使われる、xとyの二値から角度を求めるような場合には&msdn(netfx,member,System.Math.Atan2){Atan2メソッド};を使用することができます。 Atan2は引数の象限を考慮するため、引数y, xの値によってはAtanとは異なる結果になります。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    double x, y;
+

          
+
    x = 1.0; y = 1.0;
+

          
+
    Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan(y / x));
+
    Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan2(y, x));
+
    Console.WriteLine();
+

          
+
    x = 0.0; y = 1.0;
+

          
+
    Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan(y / x));
+
    Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan2(y, x));
+
    Console.WriteLine();
+

          
+
    x = -1.0; y = -1.0;
+

          
+
    Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan(y / x));
+
    Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan2(y, x));
+
    Console.WriteLine();
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim x, y As Double
+

          
+
    x = 1.0 : y = 1.0
+

          
+
    Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan(y / x))
+
    Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan2(y, x))
+
    Console.WriteLine()
+

          
+
    x = 0.0 : y = 1.0
+

          
+
    Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan(y / x))
+
    Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan2(y, x))
+
    Console.WriteLine()
+

          
+
    x = -1.0 : y = -1.0
+

          
+
    Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan(y / x))
+
    Console.WriteLine("({0}, {1}) : {2}", x, y, Math.Atan2(y, x))
+
    Console.WriteLine()
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
(1, 1) : 0.785398163397448
+
(1, 1) : 0.785398163397448
+

          
+
(0, 1) : 1.5707963267949
+
(0, 1) : 1.5707963267949
+

          
+
(-1, -1) : 0.785398163397448
+
(-1, -1) : -2.35619449019234
+

          
+
}}
+

          
+
双曲線関数はそれぞれ&msdn(netfx,member,System.Math.Sinh){Sinhメソッド};、&msdn(netfx,member,System.Math.Cosh){Coshメソッド};、&msdn(netfx,member,System.Math.Tanh){Tanhメソッド};として用意されています。
+

          
+

          
+
#navi(..)
+

          

programming/netfx/mathematics/3_complex/index.wiki.txt

current previous
1,739 0,0
+
${smdncms:title,Complex構造体}
+
${smdncms:header_title,Complex構造体 (System.Numerics)}
+
${smdncms:keywords,Complex,System.Numerics,複素数}
+
${smdncms:document_versions,codelang=cs,codelang=vb}
+

          
+
#navi(..)
+

          
+
&msdn(netfx,type,System.Numerics.Complex){Complex構造体};は.NET Framework 4より使用できるようになった構造体で、複素数を表す構造体です。 実部・虚部それぞれをDouble型の値で格納し、一つの型として扱えるようにした型となっています。
+

          
+
なお、[[BigInteger構造体>programming/netfx/mathematics/2_biginteger]]と同様、Complex構造体はアセンブリSystem.Numerics.dllに含まれています。 使用する場合は、System.Numerics.dllへの参照を追加する必要があります。
+

          
+
#googleadunit(banner)
+

          
+
*演算子
+
Complex構造体には、四則演算子・等価/不等価演算子が定義されているため、プリミティブな実数型と同じように演算式を記述することができます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Complex a = 1.0;
+
    Complex b = new Complex(0.0, 1.0);
+
    Complex c = a + b;
+

          
+
    Console.WriteLine(a);
+
    Console.WriteLine("-{0} = {1}", b, -b);
+
    Console.WriteLine("{0} + {1} = {2}", a, b, c);
+
    Console.WriteLine("{0} - {1} = {2}", a, b, a - b);
+
    Console.WriteLine("{0} * {1} = {2}", a, b, a * b);
+
    Console.WriteLine("{0} / {1} = {2}", a, b, a / b);
+

          
+
    if (a == b)
+
      Console.WriteLine("{0} == {1}", a, b);
+
    else
+
      Console.WriteLine("{0} != {1}", a, b);
+

          
+
    if (a != c)
+
      Console.WriteLine("{0} != {1}", a, c);
+
    else
+
      Console.WriteLine("{0} == {1}", a, c);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim a As Complex = 1.0
+
    Dim b As New Complex(0.0, 1.0)
+
    Dim c As Complex = a + b
+

          
+
    Console.WriteLine(a)
+
    Console.WriteLine("-{0} = {1}", b, -b)
+
    Console.WriteLine("{0} + {1} = {2}", a, b, c)
+
    Console.WriteLine("{0} - {1} = {2}", a, b, a - b)
+
    Console.WriteLine("{0} * {1} = {2}", a, b, a * b)
+
    Console.WriteLine("{0} / {1} = {2}", a, b, a / b)
+

          
+
    If a = b Then
+
      Console.WriteLine("{0} = {1}", a, b)
+
    Else
+
      Console.WriteLine("{0} <> {1}", a, b)
+
    End If
+

          
+
    If a <> c Then
+
      Console.WriteLine("{0} <> {1}", a, c)
+
    Else
+
      Console.WriteLine("{0} = {1}", a, c)
+
    End If
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
(1, 0)
+
-(0, 1) = (0, -1)
+
(1, 0) + (0, 1) = (1, 1)
+
(1, 0) - (0, 1) = (1, -1)
+
(1, 0) * (0, 1) = (0, 1)
+
(1, 0) / (0, 1) = (0, -1)
+
(1, 0) != (0, 1)
+
(1, 0) != (1, 1)
+
}}
+

          
+
また、IEquatable<BigInteger>も実装しているので、このインターフェースを使用した比較も行えます。
+
-IEquatableについての解説
+
--[[programming/netfx/comparison]]
+
--[[programming/netfx/comparison/1_equation]]
+

          
+

          
+
*型変換
+
Complex構造体は、Doubleなどの実数型、Int32などの整数型からの暗黙の型変換をサポートしています。 型変換によりComplex構造体を構築した場合、値は実部として扱われ、虚部は常に0となります。 Decimal, BigIntegerからも型変換を行うことができますが、オーバーフローや精度が失われる可能性があるため明示的な型変換を行う必要があります。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Complex a = 1.0; // double
+
    Complex b = 100; // int
+
    Complex c = (Complex)(1.0m / 3.0m); // decimal
+

          
+
    Console.WriteLine(a);
+
    Console.WriteLine(b);
+
    Console.WriteLine(c);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim a As Complex = 1.0R ' Double
+
    Dim b As Complex = 100 ' Integer
+
    Dim c As Complex = CType(1.0D / 3.0D, Complex) ' Decimal
+

          
+
    Console.WriteLine(a)
+
    Console.WriteLine(b)
+
    Console.WriteLine(c)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
(1, 0)
+
(100, 0)
+
(0.333333333333333, 0)
+
}}
+

          
+
&msdn(netfx,type,System.Drawing.PointF){PointF構造体};などからの変換はサポートされていないので、コンストラクタを使う必要があります。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Drawing;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    PointF pt = new PointF(3.0f, 4.0f);
+

          
+
    //Complex z = (Complex)pt; // CS0030: 型 'System.Drawing.PointF' を型 'System.Numerics.Complex' に変換できません
+
    Complex z = new Complex(pt.X, pt.Y);
+

          
+
    Console.WriteLine(z);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Drawing
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim pt As New PointF(3.0F, 4.0F)
+

          
+
    'Dim z = As Complex = CType(pt, Complex) ' CS0030: 型 'System.Drawing.PointF' を型 'System.Numerics.Complex' に変換できません
+
    Dim z As New Complex(pt.X, pt.Y)
+

          
+
    Console.WriteLine(z)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
また、Complex型から他の実数型・整数型へ直接変換することはできないので、実部・虚部を個別に取得して変換する必要があります。
+

          
+

          
+
*実部・虚部・絶対値・偏角
+
Complexに格納されている値の状態を知るために、次のようなプロパティが用意されています。
+

          
+
:&msdn(netfx,type,System.Numerics.Complex.Real){Real};|複素数の実部の値(Re &italic{z};)を取得する。
+
:&msdn(netfx,type,System.Numerics.Complex.Imaginary){Imaginary};|複素数の虚部の値(Im &italic{z};)を取得する。
+
:&msdn(netfx,type,System.Numerics.Complex.Magnitude){Magnitude};|複素数の絶対値(&#x7c;&italic{z};&#x7c;)を取得する。
+
返される値はMath.Sqrt(z.Real * z.Real + z.Imaginary * z.Imaginary)と同じ。
+
:&msdn(netfx,type,System.Numerics.Complex.Phase){Phase};|複素数のガウス平面上での偏角(arg &italic{z};)を取得する。 単位はラジアン。
+
返される値はMath.Atan2(z.Imaginary, z.Real)と同じ。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Complex z = new Complex(0.86603, 0.50000);
+

          
+
    Console.WriteLine(z);
+
    Console.WriteLine("Re z = {0}", z.Real);
+
    Console.WriteLine("Im z = {0}", z.Imaginary);
+
    Console.WriteLine("|z| = {0}", z.Magnitude);
+
    Console.WriteLine("arg z = {0}", z.Phase);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim z As New Complex(0.86603, 0.50000)
+

          
+
    Console.WriteLine(z)
+
    Console.WriteLine("Re z = {0}", z.Real)
+
    Console.WriteLine("Im z = {0}", z.Imaginary)
+
    Console.WriteLine("|z| = {0}", z.Magnitude)
+
    Console.WriteLine("arg z = {0}", z.Phase)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
(0.86603, 0.5)
+
Re z = 0.86603
+
Im z = 0.5
+
|z| = 1.00000398044208
+
arg z = 0.523596477499666
+
}}
+

          
+
なお、絶対値 |&italic{z};| は&msdn(netfx,type,System.Numerics.Complex.Abs){Complex.Absメソッド};でも得られます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Complex z = new Complex(0.86603, 0.50000);
+

          
+
    Console.WriteLine(z);
+
    Console.WriteLine("|z| = {0}", z.Magnitude);
+
    Console.WriteLine("|z| = {0}", Complex.Abs(z));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim z As New Complex(0.86603, 0.50000)
+

          
+
    Console.WriteLine(z)
+
    Console.WriteLine("|z| = {0}", z.Magnitude)
+
    Console.WriteLine("|z| = {0}", Complex.Abs(z))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
(0.86603, 0.5)
+
|z| = 1.00000398044208
+
|z| = 1.00000398044208
+
}}
+

          
+

          
+
*定数
+
Complex構造体には、次のような定数を参照するための静的フィールドが用意されています。
+
:&msdn(netfx,type,System.Numerics.Complex.Zero){Zero};|実部・虚部ともに0のComplex (&italic{0 + i0};)
+
:&msdn(netfx,type,System.Numerics.Complex.One){One};|実部が1、虚部が0のComplex (&italic{1 + i0};)
+
:&msdn(netfx,type,System.Numerics.Complex.ImaginaryOne){ImaginaryOne};|実部が0、虚部が1のComplex、虚数単位 (&italic{0 + i1};)
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Console.WriteLine(Complex.Zero);
+
    Console.WriteLine(Complex.One);
+
    Console.WriteLine(Complex.ImaginaryOne);
+

          
+
    Console.WriteLine("{0} * {0} = {1}",
+
                      Complex.ImaginaryOne,
+
                      Complex.ImaginaryOne * Complex.ImaginaryOne);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Console.WriteLine(Complex.Zero)
+
    Console.WriteLine(Complex.One)
+
    Console.WriteLine(Complex.ImaginaryOne)
+

          
+
    Console.WriteLine("{0} * {0} = {1}", _
+
                      Complex.ImaginaryOne, _
+
                      Complex.ImaginaryOne * Complex.ImaginaryOne)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
(0, 0)
+
(1, 0)
+
(0, 1)
+
(0, 1) * (0, 1) = (-1, 0)
+
}}
+

          
+

          
+
*極形式
+
絶対値と偏角からComplex型を構築するには、&msdn(netfx,type,System.Numerics.Complex.FromPolarCoordinates){FromPolarCoordinatesメソッド};を使います。 このメソッドを使う場合、
+
+Complex構造体は直行形式で値を格納するため、極形式→直行形式の変換が行われることによる誤差が生じる場合がある
+
+Phaseプロパティで得られる偏角は -π ~ +π の範囲に正規化されるため、メソッドに指定した偏角とは異なる値となる場合がある
+

          
+
の2点に注意が必要です。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    double r = 1.0;
+
    double theta = 4.0 * Math.PI / 3.0;
+

          
+
    Complex z = Complex.FromPolarCoordinates(r, theta);
+

          
+
    Console.WriteLine("{0}∠{1} = {2} + i{3}", r, theta, z.Real, z.Imaginary);
+
    Console.WriteLine("r = {0}", z.Magnitude);
+
    Console.WriteLine("Θ = {0}", z.Phase);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim r As Double = 1.0
+
    Dim theta As Double = 4.0 * Math.PI / 3.0
+

          
+
    Dim z As Complex = Complex.FromPolarCoordinates(r, theta)
+

          
+
    Console.WriteLine("{0}∠{1} = {2} + i{3}", r, theta, z.Real, z.Imaginary)
+
    Console.WriteLine("r = {0}", z.Magnitude)
+
    Console.WriteLine("Θ = {0}", z.Phase)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
1∠4.18879020478639 = -0.5 + i-0.866025403784438
+
r = 1
+
Θ = -2.0943951023932
+
}}
+

          
+

          
+
*共役・逆数
+
共役複素数を得るには、&msdn(netfx,type,System.Numerics.Complex.Conjugate){Conjugateメソッド};が使えます。 得られる結果は、単純に虚部の符号を反転した値をコンストラクタに指定した場合と同じです。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Complex z = new Complex(3.0, 4.0);
+

          
+
    Console.WriteLine(z);
+
    Console.WriteLine(Complex.Conjugate(z));
+
    Console.WriteLine(new Complex(z.Real, -z.Imaginary));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim z As New Complex(3.0, 4.0)
+

          
+
    Console.WriteLine(z)
+
    Console.WriteLine(Complex.Conjugate(z))
+
    Console.WriteLine(New Complex(z.Real, -z.Imaginary))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
(3, 4)
+
(3, -4)
+
(3, -4)
+
}}
+

          
+
逆数を得るには、&msdn(netfx,type,System.Numerics.Complex.Reciprocal){Reciprocalメソッド};が使えます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Complex z = new Complex(3.0, 4.0);
+

          
+
    Console.WriteLine(z);
+
    Console.WriteLine(Complex.Reciprocal(z));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim z As New Complex(3.0, 4.0)
+

          
+
    Console.WriteLine(z)
+
    Console.WriteLine(Complex.Reciprocal(z))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
(3, 4)
+
(0.12, -0.16)
+
}}
+

          
+
逆数を、1に対する除算で求める場合と、Reciprocalメソッドで求める場合の違いは、値(除数)が0だった場合の結果の違いです。 1に対する除算で逆数を求めた場合、値が0の場合は結果が非数NaNとなります。 一方で、Reciprocalメソッドで逆数を求めた場合は、値が0の場合でも結果は0となります。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Console.WriteLine(Complex.Zero);
+
    Console.WriteLine(1 / Complex.Zero);
+
    Console.WriteLine(Complex.Reciprocal(Complex.Zero));
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Console.WriteLine(Complex.Zero)
+
    Console.WriteLine(1 / Complex.Zero)
+
    Console.WriteLine(Complex.Reciprocal(Complex.Zero))
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
(0, 0)
+
(NaN (非数値), NaN (非数値))
+
(0, 0)
+
}}
+

          
+

          
+
*数学関数
+
[[Mathクラス>programming/netfx/mathematics/0_math]]に用意されている数学関数は、Complexをサポートしていません。 代わりに、これらの関数はComplex構造体のメソッドとして提供されています。 Complexには次のようなメソッドが用意されています(rはDoubleの数、z, wはComplexの数)。 Mathクラスと同様、いずれも静的メソッドです。
+

          
+
|*Complexに用意されている数学関数とそれに相当するMathクラスのメソッド
+
|~関数|~Complexのメソッド|~相当するMathクラスのメソッド|h
+
|絶対値 &#x7c;&italic{z};&#x7c;|&msdn(netfx,member,System.Numerics.Complex.Abs){Complex.Abs};(z)|[[Math.Abs>programming/netfx/mathematics/0_math#FuncAbsSign]]|
+
|累乗 &italic{z};&sup{&italic{r};};|&msdn(netfx,member,System.Numerics.Complex.Pow){Complex.Pow};(z, r)|[[Math.Pow>programming/netfx/mathematics/0_math#FuncPower]]|
+
|累乗 &italic{z};&sup{&italic{w};};|&msdn(netfx,member,System.Numerics.Complex.Pow){Complex.Pow};(z, w)|[[Math.Pow>programming/netfx/mathematics/0_math#FuncPower]]|
+
|ネイピア数の累乗 &italic{e};&sup{&italic{z};};|&msdn(netfx,member,System.Numerics.Complex.Exp){Complex.Exp};(z)|[[Math.Exp>programming/netfx/mathematics/0_math#FuncPower]]|
+
|平方根 √&italic{z};|&msdn(netfx,member,System.Numerics.Complex.Sqrt){Complex.Sqrt};(z)|[[Math.Sqrt>programming/netfx/mathematics/0_math#FuncPower]]|
+
|自然対数 ln &italic{z};|&msdn(netfx,member,System.Numerics.Complex.Log){Complex.Log};(z)|[[Math.Log>programming/netfx/mathematics/0_math#FuncLogarithmic]]|
+
|常用対数 log&sub{10}; &italic{z};|&msdn(netfx,member,System.Numerics.Complex.Log10){Complex.Log10};(z)|[[Math.Log10>programming/netfx/mathematics/0_math#FuncLogarithmic]]|
+
|対数 log&sub{r}; &italic{z};|&msdn(netfx,member,System.Numerics.Complex.Log){Complex.Log};(z, r)|[[Math.Log>programming/netfx/mathematics/0_math#FuncLogarithmic]]|
+
|三角関数 sin &italic{z};, cos &italic{z};, tan &italic{z};|&msdn(netfx,member,System.Numerics.Complex.Sin){Complex.Sin};(z), &msdn(netfx,member,System.Numerics.Complex.Cos){Complex.Cos};(z), &msdn(netfx,member,System.Numerics.Complex.Tan){Complex.Tan};(z)|[[Math.Sin, Math.Cos, Math.Tan>programming/netfx/mathematics/0_math#FuncTrigonometric]]|
+
|逆三角関数 sin&sup{-1}; &italic{z};, cos&sup{-1}; &italic{z};, tan&sup{-1}; &italic{z};|&msdn(netfx,member,System.Numerics.Complex.Asin){Complex.Asin};(z), &msdn(netfx,member,System.Numerics.Complex.Acos){Complex.Acos};(z), &msdn(netfx,member,System.Numerics.Complex.Atan){Complex.Atan};(z)|[[Math.Asin, Math.Acos, Math.Atan>programming/netfx/mathematics/0_math#FuncTrigonometric]]|
+
|双曲線関数 sinh &italic{z};, cosh &italic{z};, tanh &italic{z};|&msdn(netfx,member,System.Numerics.Complex.Sinh){Complex.Sinh};(z), &msdn(netfx,member,System.Numerics.Complex.Cosh){Complex.Cosh};(z), &msdn(netfx,member,System.Numerics.Complex.Tanh){Complex.Tanh};(z)|[[Math.Sinh, Math.Cosh, Math.Tanh>programming/netfx/mathematics/0_math#FuncTrigonometric]]|
+
|~関数|~Complexのメソッド|~相当するMathクラスのメソッド|f
+

          
+
実部・虚部が非数NaNや無限大を含む場合の動作と結果は、Mathクラスのものとほぼ同じとなります。 詳しくは各メソッドのリファレンスを参照してください。
+

          
+

          
+
*書式
+
Complex構造体は書式指定子を指定した文字列化をサポートしています。 Double型の値に適用できる書式指定文字を指定することができ、実部・虚部それぞれの値に書式が適用されます。
+

          
+
#tabpage(C#)
+
#code(cs){{
+
using System;
+
using System.Numerics;
+

          
+
class Sample
+
{
+
  static void Main()
+
  {
+
    Complex z = new Complex(0.86603, 0.500000);
+

          
+
    Console.WriteLine("{0}", z);
+
    Console.WriteLine("{0:F2}", z);
+
    Console.WriteLine("{0:E2}", z);
+
  }
+
}
+
}}
+
#tabpage(VB)
+
#code(vb){{
+
Imports System
+
Imports System.Drawing
+
Imports System.Numerics
+

          
+
Class Sample
+
  Public Shared Sub Main()
+
    Dim z As New Complex(0.86603, 0.500000)
+

          
+
    Console.WriteLine("{0}", z)
+
    Console.WriteLine("{0:F2}", z)
+
    Console.WriteLine("{0:E2}", z)
+
  End Sub
+
End Class
+
}}
+
#tabpage-end
+

          
+
#prompt(実行結果){{
+
(0.86603, 0.5)
+
(0.87, 0.50)
+
(8.66E-001, 5.00E-001)
+
}}
+

          
+
Complex型を文字列化する場合、その形式は常に "(実部, 虚部)" となります。 これ以外の形式にしたい場合は、個別に書式を指定するか、カスタム書式プロバイダを実装する必要があります。 詳しくは以下の解説を参照してください。
+
-[[programming/netfx/string/3_formatting]]
+
-[[programming/netfx/locale/1_infoes]]
+

          
+

          
+
*Complexの使用例・マンデルブロ集合
+
Complex構造体を使った例として、マンデルブロ集合の描画を行ってみます。
+

          
+
-参考
+
--[[マンデルブロ集合 - Wikipedia:http://ja.wikipedia.org/wiki/マンデルブロ集合]]
+
--[[マンデルブロー集合:http://lecture.ecc.u-tokyo.ac.jp/~cichiji/cp-05/cp-05-11-3.html]]
+

          
+
#image(mandelbrot.png,75%,実行結果)
+

          
+
#code(cs,マンデルブロ集合の描画){{
+
// csc /unsafe+ /r:System.Drawing.dll /r:System.Numerics.dll /r:System.Windows.Forms.dll mandelbrot.cs
+

          
+
using System;
+
using System.Diagnostics;
+
using System.Drawing;
+
using System.Drawing.Imaging;
+
using System.Numerics;
+
using System.Windows.Forms;
+

          
+
class Mandelbrot : Form {
+
  private static readonly Size windowSize = new Size(720, 720);
+
  private static readonly RectangleF view = RectangleF.FromLTRB(-1.5f, -1.0f, +0.5f, +1.0f);
+
  private static readonly Color colorFill = Color.White;
+
  private Bitmap bitmapMandelbrot = null;
+
  private Stopwatch stopwatch = new Stopwatch();
+

          
+
  public static void Main()
+
  {
+
    Application.EnableVisualStyles();
+
    Application.SetCompatibleTextRenderingDefault(false);
+
    Application.Run(new Mandelbrot());
+
  }
+

          
+
  public Mandelbrot()
+
  {
+
    this.ClientSize = windowSize;
+

          
+
    stopwatch.Start();
+

          
+
    bitmapMandelbrot = GenerateMandelbrotImage();
+

          
+
    stopwatch.Stop();
+
  }
+

          
+
  protected override void OnPaint(PaintEventArgs e)
+
  {
+
    e.Graphics.DrawImageUnscaled(bitmapMandelbrot, 0, 0);
+

          
+
    e.Graphics.DrawString(stopwatch.Elapsed.ToString(), SystemFonts.DefaultFont, Brushes.Black, 0.0f, 0.0f);
+
  }
+

          
+
  private Bitmap GenerateMandelbrotImage()
+
  {
+
    Bitmap bitmap = new Bitmap(this.ClientSize.Width,
+
                               this.ClientSize.Height,
+
                               PixelFormat.Format24bppRgb);
+

          
+
    BitmapData data = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),
+
                                      ImageLockMode.WriteOnly,
+
                                      PixelFormat.Format24bppRgb);
+

          
+
    RenderMandelbrot(data);
+

          
+
    bitmap.UnlockBits(data);
+

          
+
    return bitmap;
+
  }
+

          
+
  private unsafe void RenderMandelbrot(BitmapData data)
+
  {
+
    double scaleX = view.Width  / (double)data.Width;
+
    double scaleY = view.Height / (double)data.Height;
+

          
+
    for (int y = 0; y < data.Height; y++)
+
    {
+
      byte* pixel = (byte*)data.Scan0.ToPointer() + y * data.Stride;
+
      double ci = view.Bottom - y * scaleY;
+

          
+
      for (int x = 0; x < data.Width; x++)
+
      {
+
        const int nDivLimit = 200;
+
        const double magDivLimit = 2.0;
+

          
+
        double cr = view.Left + x * scaleX;
+
        Complex c = new Complex(cr, ci);
+
        Complex z = Complex.Zero; // z(0)
+

          
+
        pixel[0] = colorFill.B;
+
        pixel[1] = colorFill.G;
+
        pixel[2] = colorFill.R;
+

          
+
        for (int n = 0; n < nDivLimit; n++)
+
        {
+
          Complex zn = (z * z) + c; // z(n + 1) = z(n)^2 + c
+

          
+
          if (zn.Magnitude <= magDivLimit) {
+
            z = zn;
+

          
+
            continue;
+
          }
+
          else
+
          {
+
            Color col = FromHsv(360 * n / nDivLimit, 255, 255);
+

          
+
            pixel[0] = col.B;
+
            pixel[1] = col.G;
+
            pixel[2] = col.R;
+

          
+
            break;
+
          }
+
        }
+

          
+
        pixel += 3;
+
      } // for x
+
    } // for y
+
  }
+

          
+
  private Color FromHsv(int h, int s, int v)
+
  {
+
    if (s == 0)
+
      return Color.FromArgb(v, v, v);
+

          
+
    byte p = (byte)((v * (255 - s)) / 255);
+
    int ht = h * 6;
+
    int d = ht % 360;
+

          
+
    ht /= 360;
+

          
+
    if ((ht % 2) == 0) {
+
      // ht = 0, 2, 4
+
      byte t = (byte)((v * (255 - s * (360 - d) / 360)) / 255);
+

          
+
      switch (ht) {
+
        case 0:  return Color.FromArgb(v, t, p);
+
        case 2:  return Color.FromArgb(p, v, t);
+
        default: return Color.FromArgb(t, p, v);
+
      }
+
    }
+
    else {
+
      // ht = 1, 3 ,5
+
      byte q = (byte)((v * (255 - s * d / 360)) / 255);
+

          
+
      switch (ht) {
+
        case 1:  return Color.FromArgb(q, v, p);
+
        case 3:  return Color.FromArgb(p, q, v);
+
        default: return Color.FromArgb(v, p, q);
+
      }
+
    }
+
  }
+
}
+
}}
+

          
+
#navi(..)
+