[英]C++ random generator mt19937, is it in <random> or <bits/random.h>?
[英]Why is my mt19937 Random generator giving me ridiculous results? C++
在另一個項目上工作,我們需要使用mt19937
隨機生成數字。 我們應該讓它根據網格的部分隨機選擇一個x和y坐標。 例如,我的函數將minX
, maxX
, minY
, maxY
傳遞給函數。 我的x坐標工作正常。 我在測試運行時隨機出錯。 有時它會毫無問題地運行10次,然后出現錯誤。 我輸入了一些自調試行來顯示mt生成器實際生成的內容。 就像我說的那樣,x工作正常,y有時會工作。 它會隨機給我一個-3437892或9743903。
這是我的代碼:
void DungeonLevel::generateRoom(int minX,int maxX,int minY, int maxY){
mt19937 mt;
mt.seed( time(NULL) );
// Calculate random width and height; these both range
// from 4-13
int iRandomWidth = 4 + (mt() % 10);
int iRandomHeight = 4 + (mt() % 10);
// Calculate the start points in both X and Y directions
int iStartX;
iStartX = mt() % (maxX - iRandomWidth);
cout << "xStart: " << iStartX<<endl; //cout flag
while ((iStartX > maxX) && (iStartX >= 0)){
cout << "xStart: " << iStartX<<endl;//cout flag
iStartX = mt() % (maxX - iRandomWidth);
}
int iStartY = 0;
iStartY = mt() % (maxY - iRandomHeight);
cout<<"yStart: " <<iStartY<<endl; //cout flag
while ((iStartY > maxY)){
cout<<"yStart: " <<iStartY<<endl;//cout flag
iStartY = (mt() % (maxY - iRandomHeight));
}
// Iterate through both x and y coordinates, and
// set the tiles to room tiles
// SINGLE ROOM
for( int x = iStartX; x <= iStartX + iRandomWidth; x++ ){
for( int y = iStartY; y <= iStartY + iRandomHeight; y++ ){
if (y == iStartY){
dungeonGrid[y][x] = '-';
}
else if (iStartX == x){
dungeonGrid[y][x] = '|';
}
else if (y == (iStartY+iRandomHeight)){
dungeonGrid[y][x] = '-';
}
else if (x == (iStartX+iRandomWidth)){
dungeonGrid[y][x] = '|';
}
else {
dungeonGrid[y][x] = '.';
}
}
}
}
我認為你應該為mt19937使用隨機分布。 所以用它吧
mt19937 mt;
mt.seed( time(nullptr) );
std::uniform_int_distribution<int> dist(4, 13);
int iRandomWidth = dist(mt);
int iRandomHeight = dist(mt);
這樣,您可以保證獲得4到13之間的隨機數。
更新雖然我的答案解決了原始問題,並且在我看來代碼可讀性有所提高,但它實際上並沒有解決原始代碼中的問題。 另請參閱jogojapan的答案。
問題的最終原因是您在代碼中混合使用了有符號和無符號整數,而沒有采取必要的預防措施(並且不需要)。
具體來說,如果minY
有時小於13,那么iRandomHeight
會iRandomHeight
負數。 你得到的是類似於下面演示的效果:
#include <limits>
#include <iostream>
using namespace std;
int main()
{
/* Unsigned integer larger than would fit into a signed one.
This is the kind of thing mt199737 returns sometimes. */
unsigned int i = ((unsigned int)std::numeric_limits<int>::max()) + 1000;
cout << (i % 3) << endl;
cout << (i % -3) << endl;
cout << (signed)(i % -3) << endl;
return 0;
}
這首先生成一個略大於符合有符號整數的無符號整數。 mt19937
返回unsigned,有時會在上面的代碼中給出像i
這樣的值。
上面代碼的輸出(參見liveworkspace )如下:
2
2147484647
-2147482649
第二行顯示帶有負數的模數結果(例如iRandomHeight
有時會),應用於大於適合相應的有符號整數的無符號整數。 第三行顯示當您將其轉換回有符號整數時會發生什么(當您將其分配給您的一個有符號整數變量時,它會隱式執行)。
雖然我同意Haatschii你應該使用std::uniform_int_distribution
讓你的生活更輕松,但即使這樣,使用有符號和無符號也很重要。
弄清楚我在@haatschii的幫助下犯下的業余錯誤。
它現在非常有意義。 iStartY和iStartX對於被設置為低於或等於零的數字沒有限制。我覺得因為沒有抓住那個哈哈而感到愚蠢。 我添加了另一個循環以確保該值大於0.我還使iStartX和iStartY值以maxX + 1和maxY + 1開始,以便它們自動進入循環以生成大於0的解。
下面是解決方案代碼:
void DungeonLevel::generateRoom(int minX,int maxX,int minY, int maxY){
mt19937 mt;
mt.seed( time(NULL) );
// Calculate random width and height; these both range
// from 4-13
int iRandomWidth = 4 + (mt() % 10);
int iRandomHeight = 4 + (mt() % 10);
int iStartX = maxX+1; //automatically has to enter the second while loop
while ((iStartX > maxX) && (iStartX >= 0)){
while ((maxX - iRandomWidth) <= 0){
iRandomHeight = 4 + (mt() % 10); //makes value > 0
}
iStartX = mt() % (maxX - iRandomWidth);
}
int iStartY = maxY+1; //automatically has to enter the second loop
while ((iStartY > maxY)){
while ((maxY - iRandomHeight) <= 0){
iRandomHeight = 4 + (mt() % 10); //sets to valid value
}
iStartY = mt() % (maxY - iRandomHeight);
}
// Iterate through both x and y coordinates, and
// set the tiles to room tiles
// SINGLE ROOM
for( int x = iStartX; x <= iStartX + iRandomWidth; x++ ){
for( int y = iStartY; y <= iStartY + iRandomHeight; y++ ){
if (y == iStartY){
dungeonGrid[y][x] = '-';
}
else if (iStartX == x){
dungeonGrid[y][x] = '|';
}
else if (y == (iStartY+iRandomHeight)){
dungeonGrid[y][x] = '-';
}
else if (x == (iStartX+iRandomWidth)){
dungeonGrid[y][x] = '|';
}
else {
dungeonGrid[y][x] = '.';
}
}
}
}
謝謝提醒伙計!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.