为什么这个随机生成器总是输出相同的数字

时间:2019-10-26 04:41:15

标签: c++

我不明白为什么每次输出相同的数字,即使每次输出不同的数字也是如此。 rand()%10 + 1,应该随机输出一个1到10之间的数字,但是我的代码每次都只输出相同的精确5个数字。

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    int v1;
    for(v1=0; v1 < 10; v1++) {
        v1 = rand() % 10 + 1;
        cout << v1 << endl;
    }
    return 0;
}

3 个答案:

答案 0 :(得分:3)

您的代码的预期目标充其量是粗略的,并且您的问题描述没有任何帮助。代码本身可以采用多种方式。我认为,您正在尝试从均匀分布中绘制十个随机数。现代化的方法是这样的:

简单均匀的分布

#include <iostream>
#include <random>

int main()
{
    std::mt19937 prng{ std::random_device{}() };
    std::uniform_int_distribution<> dist(1, 10);

    for (int i = 0; i < 10; ++i)
        std::cout << dist(prng) << ' ';
    std::cout.put('\n');
}

请注意,std::mt19937是mersenne-twister prng的种子,它是使用std::random_device通过库接口连接到某些熵源的。然后使用该prng来馈送std::uniform_int_distribution的非平凡机制,这仅限于域{1..10}。请注意,这不会阻止重复。下面显示了一些示例运行(尝试时最好有所不同):

输出(可变)

7 8 3 4 4 5 8 5 5 3

无需替换的选择

如果相反,您对绘制随机选择而不进行重复感兴趣,可以通过多种方法来完成,但是我更喜欢这样的小型域,那就是简单地对数字进行排序,随机洗牌,然后迭代到绘制随机顺序。再次,我们将使用适当播种的mersenne-twister prng,但这一次,我们将其用作由库提供的随机播放序列的随机源,该序列填充了非常有限的域,可从中进行绘制:

#include <iostream>
#include <random>
#include <vector>
#include <numeric>
#include <algorithm>

int main()
{
    std::mt19937 rng{ std::random_device{}() };
    std::vector<int> vec(10);

    std::iota(vec.begin(), vec.end(), 1);
    std::shuffle(vec.begin(), vec.end(), rng);

    for (auto x : vec)
        std::cout << x << ' ';
    std::cout.put('\n');
}

输出(可变)

6 7 10 2 4 8 3 1 5 9

上面使用的重要功能:

  • std::iota是一种简单的升序数字序列生成算法
  • std::shuffle是一种随机随机播放算法,它利用您提供的RNG源执行随机播放操作。

您的代码

以上两种方法都比您似乎想做的要好。 Bias introduced with modulo against rand()可能是一个真正的问题,只有您才能确定是否真正重要。如果您想防止这种情况,请使用我之前介绍的方法之一(适合您的需要)。

也就是说,您的代码可能 仅缺少适当的种子。根据库标准,在与rand()一起查看之前,对srand的任何调用都将表现为好像使用了srand(1)。这就解释了您每次运行都会产生的重复结果。假设您同时使用v1作为控制循环变量来自rand模运算的数据持有人本身就是一个错误,那么解决这两个问题的方式将是这样:

#include <iostream>
#include <cstdlib>
#include <ctime>

int main()
{
    std::srand(static_cast<unsigned>(std::time(nullptr)));

    for (int i = 0; i < 10; ++i)
        std::cout << 1 + std::rand() % 10 << ' ';
    std::cout.put('\n');
}

输出(可变)

9 1 10 6 8 7 5 9 4 10

也就是说,我警告不要这样做。您可以在很多事情上犯错误,并且偏见总是在后台等待您咬。按保证使用其他方法之一

答案 1 :(得分:2)

您需要使用此

var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext("2d");
var p = { x: 25, y: 25 };
var velo = 3,
  corner = 50,
  rad = 20;
var ball = { x: p.x, y: p.y };
var moveX = Math.cos((Math.PI / 180) * corner) * velo;
var moveY = Math.sin((Math.PI / 180) * corner) * velo;

function DrawMe() {
  ctx.clearRect(0, 0, 400, 300);

  if (ball.x > canvas.width - rad || ball.x < rad) moveX = -moveX;
  if (ball.y > canvas.height - rad || ball.y < rad) moveY = -moveY;

  ball.x += moveX;
  ball.y += moveY;

  ctx.beginPath();
  ctx.fillStyle = "red";
  ctx.arc(ball.x, ball.y, rad, 0, Math.PI * 2, false);
  ctx.fill();
  ctx.closePath();
}

setInterval(DrawMe, 10);

答案 2 :(得分:-1)

rand()是C或C ++函数,它的编码方式使得每次我们编译和运行程序时,我们的输出必须是相同的数字序列。 有关更多信息,请参考此:rand() and srand() in C/C++ - GeeksforGeeks 这是rand - C++ Reference - Cplusplus.com

对于您的程序,您正在使用随机数更新迭代器变量,因此您应为此声明一个新变量,并根据时间使用srand(time(0))作为种子,因此您的代码应为:

#include <iostream>
#include <cstdlib>
using namespace std;
int main()
{
    int v1,v2;
    srand(time(0)); 
    for(v1=0; v1 < 10; v1++) {
        v2 = rand() % 10 + 1;
        cout << v2 << endl;
    }
    return 0;
}