悪い乱数のリスクを視覚的に明らかにする
ここでは良い乱数・悪い乱数で説明した 「上位ビットの問題」が持つリスクを明らかにする。
x += rng.NextDouble() + 1.5;
y += rng.NextDouble() + 1.5;
ごく単純なものである。


/* RandTest.cs */
using System;
using System.Drawing;
using System.Windows.Forms;
class Form1:Form {
static int Seed=0;
private void button1_Click(object sender,EventArgs e)
{
if (listBox1.SelectedIndex < 0) listBox1.SelectedIndex = 0;
Random rng = new Random();
pictureBox1.Image = new Bitmap(pictureBox1.Width, pictureBox1.Height);
Graphics g = null; SolidBrush pen0 = null, pen1 = null;
try
{
g = Graphics.FromImage(pictureBox1.Image);
pen0 = new SolidBrush(Color.Green);
pen1 = new SolidBrush(Color.Red);
for (int i = 0; i < 100; i++)
{
double x = 0, y = 0;
if (listBox1.SelectedIndex == 1) rng = new Random(Seed++);
for (int j = 0; j < 10; j++)
{
x += rng.NextDouble() + 1.5;
y += rng.NextDouble() + 1.5;
g.FillRectangle(j % 2 == 0 ? pen0 : pen1, (float)x * 20,
pictureBox1.Height - (float)y * 20, 3, 3);
}
}
}
finally { g.Dispose(); pen0.Dispose(); pen1.Dispose(); }
}
public Form1()
{
InitializeComponent();
}
/// <summary>
/// 必要なデザイナー変数です。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows フォーム デザイナーで生成されたコード
/// <summary>
/// デザイナー サポートに必要なメソッドです。このメソッドの内容を
/// コード エディターで変更しないでください。
/// </summary>
private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.listBox1 = new System.Windows.Forms.ListBox();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(6, 6);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(55, 22);
this.button1.TabIndex = 0;
this.button1.Text = "実行";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// listBox1
//
this.listBox1.FormattingEnabled = true;
this.listBox1.ItemHeight = 12;
this.listBox1.Items.AddRange(new object[] {
"1回だけ時刻を種にして初期化",
"毎回種を1ずつ増やして初期化"});
this.listBox1.Location = new System.Drawing.Point(6, 34);
this.listBox1.Name = "listBox1";
this.listBox1.Size = new System.Drawing.Size(160, 28);
this.listBox1.TabIndex = 1;
//
// pictureBox1
//
this.pictureBox1.BackColor = System.Drawing.SystemColors.Window;
this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill;
this.pictureBox1.Location = new System.Drawing.Point(0, 0);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(500, 500);
this.pictureBox1.TabIndex = 2;
this.pictureBox1.TabStop = false;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.Control;
this.ClientSize = new System.Drawing.Size(500, 500);
this.Controls.Add(this.listBox1);
this.Controls.Add(this.button1);
this.Controls.Add(this.pictureBox1);
this.Name = "Form1";
this.Text = "Form1";
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button1;
private System.Windows.Forms.ListBox listBox1;
private System.Windows.Forms.PictureBox pictureBox1;
}
static class Program {
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
このソースコードを RandTest.cs という名のファイルに保存して、コマンドプロンプトに
path C:\Windows\Microsoft.NET\Framework\v2.0.50727 または path C:\Windows\Microsoft.NET\Framework\v4.0.30319 csc /t:winexe RandTest.csと打ち込むと RandTest.exe が作られ、それを実行することで確かめることができる。