随机数生成的数组没有重复且只有奇数
Random Number generated Array without duplicates and only odd Numbers
我正在尝试生成一个充满随机数的数组,没有重复项,并且它们都必须是偶数且大于 1。遗憾的是,在我的代码中,我的数组中经常出现“0”,但我真的不知道知道如何修复它。
这是代码:
{
public int[] rArray; // our array
RandomArray(int arrayLength, int MaxValue)
{
rArray = new int[arrayLength];
Random randNum = new Random();
for(int p=0; p<arrayLength;p++)
for (int i = 0; i <= rArray.length; i++)
{
boolean exist = true;
while (exist)
{
exist = false;//
int x = randNum.nextInt(2,MaxValue);
for (int k = 0; k < i; k++)
{
if (x == rArray[k] )
{
exist = true;
break;
}
}
if (!exist && x % 2 == 0)
{
rArray[p] = x;
}
}
}
}
如何只得到奇数?
粗略地说,您有 3 个 'curves'(如带有 X 轴和 Y 轴的数字图表)可供您使用:
- 线性有限均匀曲线
可通过 .nextInt()
和随机 class 中的大多数其他方法访问,例如 .nextBytes()
- 这些会给你一个介于 0 和 B 之间的随机数(例如,B ,.nextByte()
为256,.nextInt(5)
为5,而且是均匀分布的,意思是:每个数字出现的可能性是一样的。
nextDouble()
.nextDouble()
是一个特殊的孩子 - 鉴于双打不精确,分布也不完美 - 你不能说:“它可以是 0 到 1 之间的任何数字”仅仅因为有之间有无限数量的数字,双打没有无限精度。出于随机目的,它是 'anything between 0 and 1, linear uniform',但请注意,用它进行映射会加剧 double
数学中固有的错误。
- 高斯曲线
可通过 .nextGuassian()
- a gaussian distributed curve 访问。中间的东西比更极端的数字更有可能。它继承了与 nextDouble
相同的一般精度问题。
而这 3 个就是您的全部。因此,如果您需要一个与上述 3 中的任何一个都不完全匹配的随机分布,则需要编写一个 'mapping operation' - 一个将上述 3 个中的一个作为输入并作为输出产生的函数随心所欲的随机数。
在您的具体情况下,您需要 'odd numbers'。这很容易做到:从 .nextInt()
开始,它给你任何数字,然后加 1 并乘以 2。现在你只有奇数了。
为了简单起见,取nextByte()
:它只能产生 256 个不同的值(0、1、2、3、....、255)。您可以制作一个包含 2 列的 table;左边包含每个数字。右边包含当你通过你的映射函数折腾它时它会发生什么。如果现在正确的列正是您想要的 - 瞧,你明白了。
因此,做一个函数:
public static int mapToOdd(int in) {
return 1 + in * 2;
}
然后使用mapToOdd(rnd.nextInt(maxValue))
.
为什么你得到零。
原始数组(int[]
是原始数组)从全零开始。当您的算法没有将数字放入数组的每个 'cell' 中时,您会得到它开始的任何内容,即零。
不替换如何填充
这实际上比听起来要难。有 2 个选项:您选择的是只生成一个数字,检查该数字是否有效,如果无效,则重新开始。但是你引入了一个错误:当你生成一个偶数时,exist
将是 false
,但是你的 if (!exist && x % 2 == 0)
函数也没有被输入 - 所以没有设置值(rArray[p]
仍然是 0),但是因为 exist
是假的,你的 while 循环不会循环。
另一种选择是首先生成所有个可能生成的数字,将它们存储在数组或列表中,将数组或列表打乱,然后只取前X个元素。
在 30% 点左右,效率翻转,你想要后者:假设你要 select 从 0-499 包含的随机数,并希望将它们存储在一个有 498 个槽的数组中,无需更换。您的算法(如果已经存在,则只需 re-random)将采用 AGES 作为最后几个数字。
int 的默认值为 0。当您的代码 returns 为奇数时,您没有为数组中的特定索引分配任何值。问题发生在下面 statements:
if (!exist && x % 2 == 0)
{
rArray[p] = x;
}
试试下面的代码:
private static int[] getArray(int arrayLength, int maxValue) {
int[] rArray = new int[arrayLength];
Random randNum = new Random();
for (int p = 0; p < arrayLength; p++)
for (int i = 0; i <= rArray.length; i++) {
boolean exist = true;
int x = getRandomNumber(randNum, maxValue);
while (exist) {
exist = false;//
for (int k = 0; k < i; k++) {
if (x == rArray[k]) {
exist = true;
break;
}
}
x = getRandomNumber(randNum, maxValue);
}
rArray[p] = x;
}
return rArray;
}
private static int getRandomNumber(Random random, int maxValue) {
while (true) {
int i = random.nextInt(maxValue);
if (i % 2 == 0 && i != 0)
return i;
}
}
编辑:
这样做的构造方法如下:
导入 java.util.Random;
public class RandomArray {
public int[] rArray;
RandomArray(int arrayLength, int MaxValue) {
int[] rArray = new int[arrayLength];
Random randNum = new Random();
for (int p = 0; p < arrayLength; p++)
for (int i = 0; i <= rArray.length; i++) {
boolean exist = true;
int x = getRandomNumber(randNum, MaxValue);
while (exist) {
exist = false;//
for (int k = 0; k < i; k++) {
if (x == rArray[k]) {
exist = true;
break;
}
}
x = getRandomNumber(randNum, MaxValue);
}
rArray[p] = x;
}
}
private static int getRandomNumber(Random random, int maxValue) {
while (true) {
int i = random.nextInt(maxValue);
if (i % 2 == 0 && i != 0)
return i;
}
}
}
当使用特定大小的 int[]
时,数组的值为 0,因为这是 int
(基元)的默认值。
在您的循环中,您正在检查该值是否不存在并且是否为偶数,如果不存在,您将跳过数组中留下 0 的元素。
for (int i = 0; i <= rArray.length; i++) {
boolean exist = true;
while (exist) {
exist = false;//
int x = randNum.nextInt(2,MaxValue);
for (int k = 0; k < i; k++) {
if (x == rArray[k] ) {
exist = true;
break;
}
}
if (!exist && x % 2 == 0) {
rArray[p] = x;
}
}
}
如果随机数是3,那将不存在,甚至都不存在。它将离开 while
循环,没有设置 rArray[p]
并且外循环将前进到下一个,留下 0.
你应该做的是首先检查值是否为偶数,如果不是则生成一个新的数字。
for (int i = 0; i < rArray.length; i++) {
boolean exist = true;
while (exist) {
exist = false;//
int x = 1;
while (((x = randNum.nextInt(2, MaxValue)) % 2) != 0) {}
}
for (int k = 0; k < i; k++) {
if (x == rArray[k] ) {
exist = true;
break;
}
}
if (!exist) {
rArray[i] = x;
}
}
}
现在使用流,这将更容易实现
rArray= ThreadLocalRandom.current().ints(2, MaxValue)
.filter(it -> (it % 2) == 0)
.distinct().limit(arrayLength).toArray();
会产生相同的结果。
有很多方法可以做到这一点。 答案中建议的一种有效方法是生成值,然后将它们打乱。
这可能是这样的。
- 这里,
maxValue
是你要考虑的最大值。
- 因为您只需要每隔一个值,数组的大小将是
maxValue/2
.
- 分配数组后,只需从 1 迭代到
maxValue/2
通过乘以 index by 2
. 用偶数填充数组
- 现在是洗牌的时候了。如果您使用的是
Integer
数组,则可以执行 Collections.shuffle(Arrays.asList(array))
来打乱列表,这也会打乱数组(因为数组支持列表)。但这对基元不起作用,因此包含一个用于 ints
. 基元数组的简单洗牌例程
它从 1 to maxValue
生成一个随机值,并将该位置的值与位置 maxValue
的值交换。然后 maxValue
(或其代理项,在本例中为 i
)递减,过程继续,结果返回一个打乱的数组。
请注意,返回数组的所有或第一个 limit
值都将满足要求(当然假设 limit <= maxValue/2
)
public static int[] gen(int maxValue) {
maxValue/=2;
int[] v = new int[maxValue];
for (int i = 1; i <= maxValue; i++) {
v[i-1] = i*2;
}
// time so shuffle.
Random r = new Random();
for (int i = maxValue-1; i >= 0; i--) {
int slot = r.nextInt(i+1);
int t = v[i];
v[i] = v[slot];
v[slot] =t;
}
return v;
}
我正在尝试生成一个充满随机数的数组,没有重复项,并且它们都必须是偶数且大于 1。遗憾的是,在我的代码中,我的数组中经常出现“0”,但我真的不知道知道如何修复它。 这是代码:
{
public int[] rArray; // our array
RandomArray(int arrayLength, int MaxValue)
{
rArray = new int[arrayLength];
Random randNum = new Random();
for(int p=0; p<arrayLength;p++)
for (int i = 0; i <= rArray.length; i++)
{
boolean exist = true;
while (exist)
{
exist = false;//
int x = randNum.nextInt(2,MaxValue);
for (int k = 0; k < i; k++)
{
if (x == rArray[k] )
{
exist = true;
break;
}
}
if (!exist && x % 2 == 0)
{
rArray[p] = x;
}
}
}
}
如何只得到奇数?
粗略地说,您有 3 个 'curves'(如带有 X 轴和 Y 轴的数字图表)可供您使用:
- 线性有限均匀曲线
可通过 .nextInt()
和随机 class 中的大多数其他方法访问,例如 .nextBytes()
- 这些会给你一个介于 0 和 B 之间的随机数(例如,B ,.nextByte()
为256,.nextInt(5)
为5,而且是均匀分布的,意思是:每个数字出现的可能性是一样的。
nextDouble()
.nextDouble()
是一个特殊的孩子 - 鉴于双打不精确,分布也不完美 - 你不能说:“它可以是 0 到 1 之间的任何数字”仅仅因为有之间有无限数量的数字,双打没有无限精度。出于随机目的,它是 'anything between 0 and 1, linear uniform',但请注意,用它进行映射会加剧 double
数学中固有的错误。
- 高斯曲线
可通过 .nextGuassian()
- a gaussian distributed curve 访问。中间的东西比更极端的数字更有可能。它继承了与 nextDouble
相同的一般精度问题。
而这 3 个就是您的全部。因此,如果您需要一个与上述 3 中的任何一个都不完全匹配的随机分布,则需要编写一个 'mapping operation' - 一个将上述 3 个中的一个作为输入并作为输出产生的函数随心所欲的随机数。
在您的具体情况下,您需要 'odd numbers'。这很容易做到:从 .nextInt()
开始,它给你任何数字,然后加 1 并乘以 2。现在你只有奇数了。
为了简单起见,取nextByte()
:它只能产生 256 个不同的值(0、1、2、3、....、255)。您可以制作一个包含 2 列的 table;左边包含每个数字。右边包含当你通过你的映射函数折腾它时它会发生什么。如果现在正确的列正是您想要的 - 瞧,你明白了。
因此,做一个函数:
public static int mapToOdd(int in) {
return 1 + in * 2;
}
然后使用mapToOdd(rnd.nextInt(maxValue))
.
为什么你得到零。
原始数组(int[]
是原始数组)从全零开始。当您的算法没有将数字放入数组的每个 'cell' 中时,您会得到它开始的任何内容,即零。
不替换如何填充
这实际上比听起来要难。有 2 个选项:您选择的是只生成一个数字,检查该数字是否有效,如果无效,则重新开始。但是你引入了一个错误:当你生成一个偶数时,exist
将是 false
,但是你的 if (!exist && x % 2 == 0)
函数也没有被输入 - 所以没有设置值(rArray[p]
仍然是 0),但是因为 exist
是假的,你的 while 循环不会循环。
另一种选择是首先生成所有个可能生成的数字,将它们存储在数组或列表中,将数组或列表打乱,然后只取前X个元素。
在 30% 点左右,效率翻转,你想要后者:假设你要 select 从 0-499 包含的随机数,并希望将它们存储在一个有 498 个槽的数组中,无需更换。您的算法(如果已经存在,则只需 re-random)将采用 AGES 作为最后几个数字。
int 的默认值为 0。当您的代码 returns 为奇数时,您没有为数组中的特定索引分配任何值。问题发生在下面 statements:
if (!exist && x % 2 == 0)
{
rArray[p] = x;
}
试试下面的代码:
private static int[] getArray(int arrayLength, int maxValue) {
int[] rArray = new int[arrayLength];
Random randNum = new Random();
for (int p = 0; p < arrayLength; p++)
for (int i = 0; i <= rArray.length; i++) {
boolean exist = true;
int x = getRandomNumber(randNum, maxValue);
while (exist) {
exist = false;//
for (int k = 0; k < i; k++) {
if (x == rArray[k]) {
exist = true;
break;
}
}
x = getRandomNumber(randNum, maxValue);
}
rArray[p] = x;
}
return rArray;
}
private static int getRandomNumber(Random random, int maxValue) {
while (true) {
int i = random.nextInt(maxValue);
if (i % 2 == 0 && i != 0)
return i;
}
}
编辑: 这样做的构造方法如下: 导入 java.util.Random;
public class RandomArray {
public int[] rArray;
RandomArray(int arrayLength, int MaxValue) {
int[] rArray = new int[arrayLength];
Random randNum = new Random();
for (int p = 0; p < arrayLength; p++)
for (int i = 0; i <= rArray.length; i++) {
boolean exist = true;
int x = getRandomNumber(randNum, MaxValue);
while (exist) {
exist = false;//
for (int k = 0; k < i; k++) {
if (x == rArray[k]) {
exist = true;
break;
}
}
x = getRandomNumber(randNum, MaxValue);
}
rArray[p] = x;
}
}
private static int getRandomNumber(Random random, int maxValue) {
while (true) {
int i = random.nextInt(maxValue);
if (i % 2 == 0 && i != 0)
return i;
}
}
}
当使用特定大小的 int[]
时,数组的值为 0,因为这是 int
(基元)的默认值。
在您的循环中,您正在检查该值是否不存在并且是否为偶数,如果不存在,您将跳过数组中留下 0 的元素。
for (int i = 0; i <= rArray.length; i++) {
boolean exist = true;
while (exist) {
exist = false;//
int x = randNum.nextInt(2,MaxValue);
for (int k = 0; k < i; k++) {
if (x == rArray[k] ) {
exist = true;
break;
}
}
if (!exist && x % 2 == 0) {
rArray[p] = x;
}
}
}
如果随机数是3,那将不存在,甚至都不存在。它将离开 while
循环,没有设置 rArray[p]
并且外循环将前进到下一个,留下 0.
你应该做的是首先检查值是否为偶数,如果不是则生成一个新的数字。
for (int i = 0; i < rArray.length; i++) {
boolean exist = true;
while (exist) {
exist = false;//
int x = 1;
while (((x = randNum.nextInt(2, MaxValue)) % 2) != 0) {}
}
for (int k = 0; k < i; k++) {
if (x == rArray[k] ) {
exist = true;
break;
}
}
if (!exist) {
rArray[i] = x;
}
}
}
现在使用流,这将更容易实现
rArray= ThreadLocalRandom.current().ints(2, MaxValue)
.filter(it -> (it % 2) == 0)
.distinct().limit(arrayLength).toArray();
会产生相同的结果。
有很多方法可以做到这一点。
这可能是这样的。
- 这里,
maxValue
是你要考虑的最大值。 - 因为您只需要每隔一个值,数组的大小将是
maxValue/2
. - 分配数组后,只需从 1 迭代到
maxValue/2
通过乘以index by 2
. 用偶数填充数组
- 现在是洗牌的时候了。如果您使用的是
Integer
数组,则可以执行Collections.shuffle(Arrays.asList(array))
来打乱列表,这也会打乱数组(因为数组支持列表)。但这对基元不起作用,因此包含一个用于ints
. 基元数组的简单洗牌例程
它从 1 to maxValue
生成一个随机值,并将该位置的值与位置 maxValue
的值交换。然后 maxValue
(或其代理项,在本例中为 i
)递减,过程继续,结果返回一个打乱的数组。
请注意,返回数组的所有或第一个 limit
值都将满足要求(当然假设 limit <= maxValue/2
)
public static int[] gen(int maxValue) {
maxValue/=2;
int[] v = new int[maxValue];
for (int i = 1; i <= maxValue; i++) {
v[i-1] = i*2;
}
// time so shuffle.
Random r = new Random();
for (int i = maxValue-1; i >= 0; i--) {
int slot = r.nextInt(i+1);
int t = v[i];
v[i] = v[slot];
v[slot] =t;
}
return v;
}