方法一:给定圆的半径和圆心的位置,在圆中产生均匀随机点。利用分布函数实
class RandomResult
{
double rad, xc, yc;
Random rand = new Random();
public RandomResult(double radius, double x_center, double y_center)
{
rad = radius;
xc = x_center;
yc = y_center;
}
public (double, double) randPoint()
{
double d = rad * Math.Sqrt(rand.NextDouble());
double theta = rand.NextDouble() * 2 * Math.PI;
return (d * Math.Cos(theta) + xc, d * Math.Sin(theta) + yc);
}
public double[] GetPoints()
{
int maxValue = (int)Math.Ceiling(rad);
double[] result = new double[maxValue];
maxValue -=2;
for (int i = 0; i < maxValue; i++)
{
(result[i], result[i + 1]) = randPoint();
}
return result;
}
}
方法二:Fisher-Yates洗牌算法,思路是:从原始数组中随机选择一个元素,将其与数组的第一个元素交换位置,然后从剩余的n-1个元素中随机选择一个元素,将其与数组的第二个元素交换位置,以此类推,直到遍历完所有的n个元素为止。
定义一个源数组,将指定范围数字放入源数组,随机源数组的索引,每次随机范围减1,每次随机到的索引元素值放入结果集数组中,然后将随机到的索引元素值替换为当前随机的最大索引位置元素
public static int[] randomNums3(int min, int max, int n)
{
int range = max - min + 1;
if (min > max || n < 0 || n > range)
{
return null;
}
int[] nums = new int[n];
int[] sources = new int[range];
for (int i = 0; i < range; i++)
{
sources[i] = min + i;
}
Random random = new Random();
for (int i = 0; i < n; i++)
{
int index = random.Next(range - i);
nums[i] = sources[index];
if (index != range - i - 1)
{
sources[index] = sources[range - i - 1];
}
}
return nums;
}
结果调用:
static void Main(string[] args)
{
int min = 1, max = 1_000_000, n = max - min+1;
DateTime t1 = DateTime.Now;
Console.WriteLine(randomNums3(min, max, n).Distinct().Count());
DateTime t2 = DateTime.Now;
Console.WriteLine($"用时:{t2 - t1}");
t1=DateTime.Now;
RandomResult randomResult = new RandomResult(max,1,1);
Console.WriteLine(randomResult.GetPoints().Distinct().Count());
t2 =DateTime.Now;
Console.WriteLine($"用时:{t2 - t1}");
}