Skip to content

Instantly share code, notes, and snippets.

@Kuniwak
Last active February 12, 2024 09:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kuniwak/53ea12ff871b531bd1445a504ac55e4e to your computer and use it in GitHub Desktop.
Save Kuniwak/53ea12ff871b531bd1445a504ac55e4e to your computer and use it in GitHub Desktop.
GitHub Copilot に [0-100) の区間でその分布が正規分布に従う関数を実装させてみた実験例
namespace Playground.CopilotTDD;
public static class NumberGenerator
{
public static int GetBetween0To100BySeed(int seed)
{
return new Random(seed).Next(0, 100);
}
}
namespace Playground.CopilotTDD;
public static class NumberGenerator
{
public static int GetBetween0To100BySeed(int seed)
{
return seed % 100;
}
}
// https://chat.openai.com/share/a75ee402-3131-4ee8-9a9d-54bf1b81071c
using System;
namespace Playground.CopilotTDD.Tests
{
public static class NumberGenerator
{
public static int GetBetween0To100BySeed(int seed)
{
// 線形合同法のパラメータ
const int a = 1103515245;
const int c = 12345;
const long m = (1L << 31);
// 線形合同法による疑似乱数生成
long nextSeed = (a * seed + c) % m;
int randomNumber = (int)(nextSeed % 100);
// 特定の条件下で最頻値を 50 に調整
if (randomNumber == 50 && seed % 2 == 0)
{
return 50;
}
else if (randomNumber < 50)
{
return randomNumber + 1;
}
else
{
return randomNumber;
}
}
}
}
using System;
public class NormalRandom
{
private Random random;
public NormalRandom(int seed)
{
random = new Random(seed);
}
public double NextDouble()
{
double u1 = 1.0 - random.NextDouble(); //uniform(0,1] random doubles
double u2 = 1.0 - random.NextDouble();
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) *
Math.Sin(2.0 * Math.PI * u2); //random normal(0,1)
double randNormal =
50 + 25 * randStdNormal; //random normal(mean,stdDev^2)
return randNormal;
}
}
// https://chat.openai.com/share/4e565592-6956-4cc8-9fdf-c319f2e23342
using System;
public class NormalRandom
{
private Random random;
private double? spareValue;
public NormalRandom(int seed)
{
random = new Random(seed);
spareValue = null;
}
public double NextDouble(double mean = 50, double stdDev = 25)
{
if (spareValue.HasValue)
{
double temp = spareValue.Value;
spareValue = null;
return Math.Min(Math.Max(temp * stdDev + mean, 0), 99.9999999);
}
else
{
double u1, u2, s;
do
{
u1 = 2.0 * random.NextDouble() - 1.0;
u2 = 2.0 * random.NextDouble() - 1.0;
s = u1 * u1 + u2 * u2;
}
while (s >= 1.0 || s == 0);
s = Math.Sqrt((-2.0 * Math.Log(s)) / s);
spareValue = u2 * s;
return Math.Min(Math.Max(u1 * s * stdDev + mean, 0), 99.9999999);
}
}
}
namespace Playground.CopilotTDD.Tests;
using NUnit.Framework;
using System.Collections.Generic;
public class NumberGeneratorTests
{
private const int NumberOfTryThatFollowLawOfGreatNumbers = 1_000_000;
[Test]
public void GetBetween0To100BySeed_return_a_value_that_is_between_0_to_100()
{
var map = new Dictionary<int, int>();
for (var i = 0; i < NumberOfTryThatFollowLawOfGreatNumbers; i++)
{
var seed = i;
int o = NumberGenerator.GetBetween0To100BySeed(seed);
if (map.ContainsKey(o))
{
map[o]++;
}
else
{
map.Add(o, 1);
}
}
Assert.That(map.Keys, Has.All.GreaterThanOrEqualTo(0).And.All.LessThan(100));
}
[Test]
public void GetBetween0To100BySeed_return_a_different_value_for_different_seed()
{
for (var i = 0; i < NumberOfTryThatFollowLawOfGreatNumbers; i++)
{
var seed = i;
int o1 = NumberGenerator.GetBetween0To100BySeed(seed);
int o2 = NumberGenerator.GetBetween0To100BySeed(seed + 1);
Assert.That(o1, Is.Not.EqualTo(o2));
}
}
[Test]
public void GetBetween0To100BySeed_return_a_value_that_is_deterministic()
{
for (var i = 0; i < NumberOfTryThatFollowLawOfGreatNumbers; i++)
{
var seed = i;
int o1 = NumberGenerator.GetBetween0To100BySeed(seed);
int o2 = NumberGenerator.GetBetween0To100BySeed(seed);
Assert.That(o1, Is.EqualTo(o2));
}
}
[Test]
public void GetBetween0To100BySeed_return_mode_is_50()
{
var map = new Dictionary<int, int>();
for (var i = 0; i < NumberOfTryThatFollowLawOfGreatNumbers; i++)
{
var seed = i;
int o = NumberGenerator.GetBetween0To100BySeed(seed);
if (map.ContainsKey(o))
{
map[o]++;
}
else
{
map.Add(o, 1);
}
}
var max = 0;
var mode = 0;
foreach (var kv in map)
{
if (kv.Value > max)
{
max = kv.Value;
mode = kv.Key;
}
}
Assert.That(mode, Is.EqualTo(50));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment