PDA

View Full Version : "do while problem"



Hardstyle
17th June 2010, 11:49
int math[20][20],aux2,aux3;
for(int i=0;i<40s;i++)
{
do{
aux2=int( rand()%20);
aux3=int( rand()%20);}
while(math[aux2][aux3]==0);
math[aux2][aux3]=1;
}

this should make me 40 of math's element to be 1...and it give @ 30-38 numbers....not exactly 40 ....why ???
("rand()" is working good...)

SneakyPeterson
17th June 2010, 12:26
You are making several errors here. First of all, you never initialize the math[][] array to have values of 0, so while the dowhile loop exited after one execution, depending on what machine you run it on, you can run into problems. You are really a lot safer initializing the array so that all values are equal to 0. I think the behavior that you are experiencing on your machine is that since the array is uninitalized all values within it are assumed to be 0, and thus you will never have a case where you break from your while loop. Also, the reason that only 30ish numbers are being set as one is because even though you have 400 possible numbers that you can set (20*20), you are setting 40 numbers randomly, so there's a chance that your random number generator can give you repeat values. So that difference that you're seeing in between 40 and the number of 1's you have is the number of repeat values that you generate. This error should go away once you take care of initialization.
Also, there is a flaw in your logic. I'm thinking that you want to set 40 random 0's to 1's. With your current code, you will trigger an infinite loop in an actual initialized array. Thus you need to modify your setting algorithm slightly.
So, the lesson to learn here is that you never play around with any variables that you haven't initialized and ermmm, make sure that you really understand what do-while does.

May I suggest:


int math[20][20],aux2,aux3;

for(int i = 0; i < 20; i++)
{
for(int j = 0; i < 20; j++)
{
math[i][j] = 0;
}
}

for(int i=0;i<40;i++)
{
bool set = false;
while(!set)
{
aux2=int( rand()%20);
aux3=int( rand()%20);
if(math[aux2][aux3]==0)
{
math[aux2][aux3] = 1;
set = true;
}
}
}

Hardstyle
17th June 2010, 13:15
same problem

SixDegrees
17th June 2010, 13:40
On the first pass through the array, all elements are zero. Then, they start getting set to one - unless they're already set to one, in which case the loop does nothing at all.

You will almost inevitably wind up with fewer elements set to one than there are loop iterations, because on subsequent passes the chances of encountering an element that is already set to a non-zero value increases.

Try using a while loop construct and incrementing a counter for each successful assignment. Break out of the loop when your counter reaches whatever number of set cells you like.

SixDegrees
17th June 2010, 13:54
Note, also, that you are currently only filling the array to 10% density. As the density increases, you will get more and more cases where nothing happens, and the amount of time the loop takes to complete will soar.

A better approach would be to construct some other data structure - say, a vector of pairs of integers that represent the indices of your final array - and remove an element from it with each iteration, generating your random number based on the number of remaining elements. Once you've removed 40 elements (or however many you need) you can populate the actual array from the information that's left in the vector.

SneakyPeterson
17th June 2010, 13:55
Did you make sure to add this code?



bool set = false;
while(!set)
{
aux2=int( rand()%20);
aux3=int( rand()%20);
if(math[aux2][aux3]==0)
{
math[aux2][aux3] = 1;
set = true;
}
}


The while loop should keep running until you have set a value to 0. This added in conjunction with the initialization to 0 should fix your problem. Also, if you have the bool in the wrong place then the loop will
not work.

SneakyPeterson
17th June 2010, 14:05
Something else just came to mind. For your program, I was assuming that you did it earlier, but did you make sure to include

#include <time.h>
to your includes and

srand(time(0));
to the beginning of your code execution? If you do not initialize your random number seed, then you will be generating
the same random numbers every time your code executes.

Hardstyle
17th June 2010, 20:48
#include<stdlib.h>
#include<qmessagebox.h>
#include<time.h>
void MainWindow::ButtonHandler()
{
int math[20][20];
for (int row = 1; row < 20; row++) {
for (int col = 1; col < 20; col++) {
math[row][col]=0;}}
int aux2=0;
int aux3=0;
srand(time(NULL));
for(int i=0;i<100;i++)
{
bool set = false;
while(!set)
{
aux2=int( rand()%20);
aux3=int( rand()%20);
if(math[aux2][aux3]==0)
{
math[aux2][aux3] = 1;
set = true;
}
}

}
int demonstration=0;
for (int row = 1; row < 20; row++) {
for (int col = 1; col < 20; col++) {
if(math[row][col]==1)demonstration++;}}
QMessageBox *msg=new QMessageBox;
msg->setText(QString::number(demonstration));
msg->show();

}

and it dosn't all time give 100!!!(i'v made this program just to show you...)

Archimedes
17th June 2010, 21:30
1) Arrays in C/C++ always start from '0' not '1'
So in your loops is: for ( int row = 0; row < 20; ++row) { ... }

2) In lines 16-25 of the posted code, the moment you find a value of 0 and make it 1 you have also set=true which will terminate the loop. That is the loop will run only 1 time cause everything in the array is set to 0 and so the 1st value it'll find will be 0!!! So instead of checking the value set, make a variable that counts to 40 and then terminate the loop.

3) You **probably** not have exactly 40 values set to 1 because there's a possibility that aux2 and aux3 take values that points to an element already set to 1. If you have 39 elements set to 1 there's a ~10% possibility to select an element set to 1.

SneakyPeterson
18th June 2010, 08:14
2) In lines 16-25 of the posted code, the moment you find a value of 0 and make it 1 you have also set=true which will terminate the loop. That is the loop will run only 1 time cause everything in the array is set to 0 and so the 1st value it'll find will be 0!!! So instead of checking the value set, make a variable that counts to 40 and then terminate the loop.

That loop will run until a value is set to 1. It is SUPPOSED to terminate after setting exactly one value that is a 0 to 1. The fact that it gets called 100 times should guarantee that 100 seperate 0's are changed to 1. I think that the main reason that Hardstyle isn't always getting 100 1's is because he's ignoring a whole bunch of values by starting his arrays at 1 instead of 0. Of course you aren't going to find all 100 1's if you only check part of the array!

General structure of a for loop that iterates through an array should be:

for(int i = 0; i < count; i++)

NOT

for(int i = 1; i < count; i++)

Hardstyle
18th June 2010, 10:14
1) Arrays in C/C++ always start from '0' not '1'
So in your loops is: for ( int row = 0; row < 20; ++row) { ... }

2) In lines 16-25 of the posted code, the moment you find a value of 0 and make it 1 you have also set=true which will terminate the loop. That is the loop will run only 1 time cause everything in the array is set to 0 and so the 1st value it'll find will be 0!!! So instead of checking the value set, make a variable that counts to 40 and then terminate the loop.

3) You **probably** not have exactly 40 values set to 1 because there's a possibility that aux2 and aux3 take values that points to an element already set to 1. If you have 39 elements set to 1 there's a ~10% possibility to select an element set to 1.


2) In lines 16-25 of the posted code, the moment you find a value of 0 and make it 1 you have also set=true which will terminate the loop. That is the loop will run only 1 time cause everything in the array is set to 0 and so the 1st value it'll find will be 0!!! So instead of checking the value set, make a variable that counts to 40 and then terminate the loop.

That loop will run until a value is set to 1. It is SUPPOSED to terminate after setting exactly one value that is a 0 to 1. The fact that it gets called 100 times should guarantee that 100 seperate 0's are changed to 1. I think that the main reason that Hardstyle isn't always getting 100 1's is because he's ignoring a whole bunch of values by starting his arrays at 1 instead of 0. Of course you aren't going to find all 100 1's if you only check part of the array!

General structure of a for loop that iterates through an array should be:

for(int i = 0; i < count; i++)

NOT

for(int i = 1; i < count; i++)


dude i know that in c++ array like all programing languages starts with 0

and SneakyPeterson's is right about the "2)"
the "3)" is why i use that loop ...if the aux2 and aux3 gets a value that is allrdy 1 it will redo the random thing until it will find a value that is 0....


can u please stop answering newbish and give answers only if you have any idea about the problem?

SneakyPeterson
18th June 2010, 10:44
dude i know that in c++ array like all programing languages starts with 0
So then why are you starting your arrays at 1?


and SneakyPeterson's is right about the "2)"
the "3)" is why i use that loop ...if the aux2 and aux3 gets a value that is allrdy 1 it will redo the random thing until it will find a value that is 0....
can u please stop answering newbish and give answers only if you have any idea about the problem?

While Archimedes was incorrect about the function of the loop, he did correctly diagnose your original problem of starting your array at the wrong point and thus, missing several int's when counting the number of set 1's. Please note that because you start at 1 in your first array as well, you never completely initialize your array properly. Your last comments seem a bit hostile to people who are trying to help you solve your problem and in my opinion, have done so at this point.