I'm using rand() for two ints, between 0 and 2. It appears that the first int is never 0 while the second int is 2. Here is my test code-
#include <iostream>
#include <time.h>
int main()
{
srand(time(NULL));
int number1, number2;
number1 = rand() % 3;
number2 = rand() % 3;
printf("%i, %i", number1, number2);
return 0;
}
Output-25 tries
2, 2
2, 2
2, 1
1, 2
0, 1
2, 2
1, 2
1, 0
2, 1
1, 0
0, 0
1, 2
2, 2
0, 0
2, 1
1, 0
2, 2
1, 0
2, 1
1, 0
0, 1
1, 2
1, 0
0, 0
2, 2
As you can see, out of 25 tries, the combo was never 0, 2. Is this the sign that I should probably move over to < random >? In addition, there is never 2, 0.
No, this will happen for 9*(1-1/9)^25 = 0.4736 of all seeds, or roughly 50% of the time. That is, some two digit sequence with digits in {0,1,2} will be missing from your first 25 results roughly half the times you run your program.
Run it again and see what happens.
You should definitely use <random>. The sooner you forget about rand's existence, the happier you will be.
rand is sometimes implemented with a linear congruential generator (LCG). LCGs suffer from a number of defects, the most relevant being that that the low-order bits of sequentially generated numbers are highly correlated. For this reason, you should never use rand() % k to generate numbers in the range [0, k). There are other reasons. In fact, generating unbiased random integers from a restricted range involves some subtleties, which <random> handles for you.
srand(time(NULL)) seeds the random number generator to the current time in seconds from epoch, which means that if you run the program several times in sequence, the seeds will be either the same or similar. If the seeds are the same, the random number sequence will also be the same. If the seeds are similar, the random number sequences may also be similar. So don't do this except in long-running programs. Finding a good seed for a pseudo random number generator can be tricky. <random> implementations will have better default behaviour, so you won't normally need to worry about this.
Taking % 3 does not depend on just lower order bits.
I ran the program below using VC++ simulating running the OP's program ten million times with one second between invocations. It shows no bias.
start = 1413167398
(0, 0) 1110545
(0, 1) 1111285
(0, 2) 1111611
(1, 0) 1111317
(1, 1) 1111666
(1, 2) 1110451
(2, 0) 1111580
(2, 1) 1110491
(2, 2) 1111054
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <map>
#include <utility>
int main()
{
std::map<std::pair<int, int>, int> counter;
unsigned int start = static_cast<unsigned int>(std::time(nullptr));
std::cout << "start = " << start << std::endl;
unsigned int finish = start + 10000000;
for (unsigned int seed = start; seed != finish; ++seed)
{
std::srand(seed);
int x = rand() % 3;
int y = rand() % 3;
++counter[std::make_pair(x, y)];
}
for (auto iter = counter.cbegin(); iter != counter.cend(); ++iter)
{
std::cout << "(" << iter->first.first << ", " << iter->first.second << ") ";
std::cout << iter->second << std::endl;
}
return 0;
}
It is. This code gave me 0,2 pair just at first run:
for( int i = 0; i < 20; ++i) {
number1 = rand() % 3;
number2 = rand() % 3;
printf("%i, %i\n", number1, number2);
}
Generating truly random number from uniform distribution doesn't guarantee that given (possible) number will appear in limited number of trials. The K2 out of four BSI criteria of good PRNG is
K2 — A sequence of numbers which is indistinguishable from 'true
random' numbers according to specified statistical tests.
thus generating pseudo random numbers ofcourse tends to behave in the same way as sampling from true random distribution - though because of limitations any (possible) number will appear at some point (at time less or equal its period).
http://ideone.com/c5oRQL
Use std::uniform_int_distribution
Apart from the above rand() is not the best generator. It introduces bias always whenever the divisor in modulo operation doesn't evenly divides the range of PRNG. Operator % makes the probability distribution produced in this way skewed because RAND_MAX which is maximum value for rand() can be not equal to k * 3 + 2. If divisor not evenly divides the range then distribution will be skewed and the bias increases with divisor. You can read here more on this. Summing it up: in C++ you should use <random> library:
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 gen( rd());
std::uniform_int_distribution<> dis( 0, 2);
for ( int n = 0; n < 25; ++n)
std::cout << dis(gen) << ' ';
std::cout << '\n';
}
Related
I am wondering how to generate EXACTLY the same random numbers using my personal computer and clusters.
Here is a simple code.
#include <iostream>
#include <random>
int main()
{
int N = 10;
for (int j = 0; j < N; j++) std::cout << rand() % 10 << " ";;
}
The output from my personal computer is:
1
7
4
0
9
4
8
8
2
4
The output from cluster is:
3
6
7
5
3
5
6
2
9
1
The difference of these random number will strongly affect my calculations. Moreover, my problem is very flexible and I cannot use the generated random numbers from my personal computer and use it as input on cluster. I hope to generate the same random numbers on different platform.
///////// new try:
I tried the solution in the link: If we seed c++11 mt19937 as the same on different machines, will we get the same sequence of random numbers
I used the code:
#include <random>
#include <iostream>
int main()
{
/* seed the PRNG (MT19937) using a fixed value (in our case, 0) */
std::mt19937 generator(0);
std::uniform_int_distribution<int> distribution(1, 10);
/* generate ten numbers in [1,10] (always the same sequence!) */
for (size_t i = 0; i < 10; ++i)
{
std::cout << distribution(generator) << ' ';
}
std::cout << std::endl;
return 0;
}
On my PC, I got the output: 5 10 4 1 4 10 8 4 8 4
On cluster, I got: 6 6 8 9 7 9 6 9 5 7
Still, it is different.
Can anyone give me an example of the code?
Thanks a lot.
This question explains that a sequence of numbers you get from
std::uniform_int_distribution<int> distribution(1, 10);
is implementation defined even if you use the same PRNG with the same seed. In contrast, the sequence of random numbers produced by PRNG std::mersenne_twister_engine is well-defined in any standard-conforming implementation.
So, the simplest way to get a well-defined sequence of pseudo-random numbers without using external libraries is this:
#include <iostream>
#include <random>
int main() {
std::mt19937 generator(0);
while (true) {
const auto rand = generator() % 10;
std::cout << rand << ' ';
}
}
This code is guaranteed to always produce the same sequence, 4 9 3 0 3 9 7 3 7 3 .... These numbers are not uniformly distributed for the same reason why those produced by rand() % 10 are not. If you don't care much about quality of random numbers, this may be an acceptable solution.
Really easily you can use a fixed seed for the random function. Doing so you will always end up with the same sequence on the PC and on the cluster.
#include <iostream>
#include <random>
#define FIXED_SEED 12345 // It can be any integer
int main()
{
int N = 10;
srand(FIXED_SEED)
for (int j = 0; j < N; j++)
std::cout << rand() % 10 << " ";;
}
More over since you're using C++ you can use C++ random machine to genarate pseudo-random sequences. You can obtain the same result with them, but the distribution is more precise, not a big deal anyway.
I have generated 100 random numbers, where I have to shorted out equal even and odd numbers of the random numbers. All even or odd numbers can not be repetitive.
For example I will create 100 random numbers
#include <iostream>
#include <cstdlib>
int main()
{
for (int i=1; i <=100; ++i){
//double p = rand();
std::cout <<"random number is :" << rand()<<std::endl;
}
}
Since I don't know if the even and odd numbers are same in the list from the 100 random numbers, I want to pick minimum number of pair even and odd numbers. I also will like to know what the total odd and even numbers are generated separately. One note is that, if for an example, any even or odd number get printed out multiple times, I want to consider that as a one.
For example. Let's assume we have 60 even and 40 odd numbers from the printed random numbers. And also from the 60 even numbers 10 even numbers are repetitive. So I would consider the different event numbers are 50. The printed out numbers would be first 20 even numbers and first 20 odd numbers.
The reason I want to do this is because I want to learn How I can filter out the even and odd numbers from the for loop of random generator.
UPDATE:
My goal is to find even and odd numbers from the generated random numbers. When I short out the even and odd numbers, all the even and odd numbers will be different. Which means, if I found even number 2 printed out 5 times, I would still consider that one. In this way I want to find the minimum number of even and odd numbers.
Lets have an example:
the generated print out is: {1,2,2,3,4,5,6,8,9,3,2,4,6,10}
From the list the even and odd numbers would be:
even = {2,4,6,8}
odd = {1,3,5,9}
If you looked carefully, I excluded 10 from the even shorting. The reason is that, If i added 10 in the even list, I would have more even than odd.
Use std::unorderd_set to create odd set and even set
to check number is odd = (num&1) will be 1 for odd and 0 for even
std::unordered_set<int> set_odd;
std::unordered_set<int> set_even;
for (int num : nums) {
if (num & 1) set_odd.insert(num);
else set_even.insert(even);
}
This will do what you explained in your example.
#include <set>
#include <vector>
int main()
{
std::vector<int> numbers = {1, 2, 2, 3, 4, 5, 6, 8, 9, 3, 2, 4, 6, 10};
std::set<int> even, odd;
// sort the numbers into even and odd sets
for (auto const& n : numbers)
{
if (n % 2 == 0)
even.insert(n);
else
odd.insert(n);
}
// figure out which set is smaller
int min = std::min(even.size(), odd.size());
// print out the evens
std::cout << "even = ";
auto it = even.begin();
for(int i = 0; i < min; ++i)
{
std::cout << *(it++) << " ";
}
std::cout << std::endl;
// print out the odds
std::cout << "odd = ";
it = odd.begin();
for(int i = 0; i < min; ++i)
{
std::cout << *(it++) << " ";
}
std::cout << std::endl;
}
If you only want pairs of random numbers (pair as in collection of 2-integers, one even, one odd, not std::pair), you need a way to generate the numbers, provide storage for the pairs, and keep track of the number of odds generated and number of evens generated and a way to associate the pairs of numbers generated.
To generate the random numbers std::random_device provides random number generation for int from your choice of random number engines such as the std::mersenne_twister_engine. You can generate a number within a std::uniform_int_distribution simply by declaring the device, seeding the generator with the device and then creating a distribution between a min and max of your choice.
To setup and generate random numbers within the positive range of int you could do:
...
#include <random>
#define NMAX std::numeric_limits<int>::max()
...
std::random_device rd; /* delcare the randon number generator device */
std::mt19937 gen(rd()); /* standard mrsene_twister engine seeded w/rd */
std::uniform_int_distribution<int> dist(0, NMAX); /* create disribution */
And to request a number from the distribution, simply:
int r = dist(rd); /* generate rand */
How to store the pairs generated depends on how you coordinate adding the even and odd numbers generated to coordinate storing pairs of numbers together. You can use a std::map or std::unordered_map or simply use an even and odd std::vector<int>. Using the latter allows you to fill an vector of evens and a vector of odds and then simply output the lesser .size() of the two to capture the pairs of even-odd generated out of our 100 random integers.
For example:
#define MAXRAND 100
...
std::vector<int> even, odd;
...
for (int i = 0; i < MAXRAND; i++) { /* loop MAXRAND times */
int r = dist(rd); /* generate rand */
if (r % 2 == 0) /* if even */
even.push_back(r); /* add to even vector */
else /* odd number */
odd.push_back(r); /* add to odd vector */
}
That way you can specify to generate 100 random numbers and you end up with however many even-odd pairs were generated out of those 100 random numbers -- which sounds like what you were asking.
Putting it altogether you could do:
#include <iostream>
#include <iomanip>
#include <random>
#include <vector>
#define NMAX std::numeric_limits<int>::max()
#define MAXRAND 100
int main (void) {
std::vector<int> even, odd;
std::random_device rd; /* delcare the randon number generator device */
std::mt19937 gen(rd()); /* standard mrsene_twister engine seeded w/rd */
std::uniform_int_distribution<int> dist(0, NMAX); /* create disribution */
size_t limit = 0;
for (int i = 0; i < MAXRAND; i++) { /* loop MAXRAND times */
int r = dist(rd); /* generate rand */
if (r % 2 == 0) /* if even */
even.push_back(r); /* add to even vector */
else /* odd number */
odd.push_back(r); /* add to odd vector */
}
/* output results */
limit = (even.size() > odd.size()) ? odd.size() : even.size();
std::cout << limit << " even-odd pairs (0 - " << NMAX << ")\n\n";
for (size_t p = 0; p < limit; p++)
std::cout << std::setw(12) << even.at(p) <<
" " << odd.at(p) << '\n';
}
Example Use/Output
Running you will generally generate between 40-50 pairs of numbers -- the random distributions being fairly good, e.g.
$ ./bin/evenoddpairs
48 even-odd pairs (0 - 2147483647)
1513290664 712950177
2014370968 990873219
161619218 6719997
2062410942 1965300831
2072442520 938385103
669324326 1957687455
1201350414 2134189381
217290372 1304388089
726760634 232069103
2086887656 1784024967
1345123406 185879429
1706842790 686104759
1034648158 268926351
1445724500 1996600823
1303450734 1890287253
763120758 1581912187
1788401668 1537971261
1542967608 1842999149
377964104 1995119937
87264498 644262155
224210492 519040373
692262016 372293591
502458404 1867793795
575578512 751306553
373162704 170423471
1502626218 152785903
284546326 287967359
388031960 1233214425
1839930048 243652639
465469190 1747259241
1488469408 252779515
2144753340 1992139979
2010564888 298805387
917820234 187798339
1204892922 1454685783
563347322 50283749
1303887182 345841727
1429521892 1668482773
702286146 1191166889
1490493310 963750729
986716484 1522036479
1107465502 1445768043
1613852374 1307939505
1584334086 1565159437
1325156802 354726127
1165679412 1618569419
1192475084 1341169211
71913214 1569003463
There are many ways to put this together, but given your constraint of generating 100 random numbers and then collecting only the even-odd pairs created out of those 100 numbers, the even/odd vectors is a simple to ensure you ended up with only the pairs generated out of the 100. Let me know if that is what you were asking or if you were asking something slightly different.
If you need to enforce only unique random numbers, you can fill an std::unordered_map from your two vectors.
Here is my code
#include <iostream> //cout, cin
#include <time.h> // time
#include <stdlib.h> // srand(), rand()
using std::cout; //cout
int main()
{
srand(time(NULL)); //Initializes a random seed
int rand_number = rand() % 1 + 100; //Picks a random number between 1 and 100
cout << rand_number << std::endl;
}
For some reason, it keeps giving me 100 when I generate the random number. Though I don't believe it should because I called srand(time(NULL)) to initialize a seed.
As said in the comments, rand() % 1 is nonsensical. The remainder of anything divided by 1 is 0. You then add 100 to it.
Instead, (rand() % 100) + 1 will give you a random number in the range [1, 100].
The facilities in <random> are much better, and it is a good idea to learn them.
std::mt19937 mt((std::random_device()())); //create engine
std::uniform_int_distribution<int> dist(1, 100); //define distribution
dist(mt); //better random number in range [1, 100]
I'm very new to C++, and programming in general. I decided that I wanted to make a "Guess the Number" game, but I wanted see how many guesses on average it would take the computer to guess a number between 1 and 10,000,000.
The easiest way that I could think of finding the "secret" number was to
1. take the range and divide it by two(divisor) and that would be the guess.
a. if the guess is greater than the "secret" number, then the guess-1 becomes the new maximum of the range, and I go back to step 1.
b. if the guess is lower than the "secret" number, then the guess+1 becomes the new minimum of the range and I go back to step 1.
This repeats until the number is found. From my experience, it takes the computer 22 guesses to guess the "secret" number.
For fun, I wanted to see what would happen if I changed the divisor. I was actually a bit surprised by the results for 1,000,000 iterations of trying to guess the number between 1 and 10,000,000 for a range of divisors from 2 to 10.
Average with divisor 2 is 22.3195
Average with divisor 3 is 20.5549
Average with divisor 4 is 20.9087
Average with divisor 5 is 22.0998
Average with divisor 6 is 23.1571
Average with divisor 7 is 25.5232
Average with divisor 8 is 25.927
Average with divisor 9 is 27.1941
Average with divisor 10 is 28.0839
I would love to understand why when the divisors 3, 4, and 5, are used the computer is able to, on average, use less guesses to find the "secret" number.
My code is below.
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <vector>
using namespace std;
int half_search(int a, int b, int n, int m)
{
int aMax = b;
int aMin = a;
int divisor = m;
int result;
static int counter = 0;
double guess = ((static_cast<double>(b) - a) / divisor) + aMin;
if(guess - static_cast<int>(guess) >= 0.5)
guess = ceil(guess);
if(guess < n)
{
aMin = guess + 1;
counter++;
half_search(aMin, aMax, n, divisor);
}
else if(guess > n)
{
aMax = guess - 1;
counter++;
half_search(aMin, aMax, n, divisor);
}
else
{
counter++;
result = counter;
counter = 0;
return result;
}
}
int main()
{
const int MIN = 1;
const int MAX = 10000000;
int k = 0;
int j = 2; //represents lowest divisor
int l = 10; //represent highest divisor
int iterations = 100000;
double stepSum = 0;
vector<int> myVector(iterations);
srand(1);
while(j <=10)
{
while(k < iterations)
{
int n = rand() % MAX + 1;
myVector[k] = half_search(MIN, MAX, n, j);
stepSum += myVector[k];
k++;
}
cout << "Average with divisor " << j << " is " << stepSum / iterations << endl;
j++;
k = 0;
stepSum = 0;
}
return 0;
}
On some compilers (e.g Visual Studio 2013) int n = rand() % MAX + 1; will only provide a number between 1 and 32768 because RAND_MAX can be as low as 32767.
If your random number is quite small this will bias in favour of a larger divisor.
Consider using <random> in C++11 instead. Something like:
std::random_device rd;
std::mt19937 mt(rd());
std::uniform_int_distribution<> dist(1, MAX);
//...
int n = dist(mt);
The division by 2 would be always faster, and increment the performance, because it is easier for the CPU and takes less clock cycles. This is known as Binary Search.
By using other divisor, you could have less "guesses" until the point that it has to ask to many times where the "secret" is greater or lower than the "guess".
I also see best result with divisor 2. This also should be the case Because by using divisor 2 you are only employing binary search algorithm as each time your input set would be halved.
I was toying around with arrays, populating with pseudo random numbers, finding minimum and maximum values and their indices and number of occurrences and I noticed something strange - when using srand seeded with time the number of minimum and maximum value occurrences is ALWAYS equal. This doesn't seem very random to me.
Is there an alternative way of getting a DIFFERENT number of minimum and maximum value occurrences, as one would expect with random numbers?
Here is my code (I am learning so it may be messy and inefficient, recommendations are welcome)
#include <cstdlib>
#include <iostream>
#include <time.h>
using namespace std;
void findExtremes( const int[], int);
int main()
{
const int lenght = 2000; //define lenght
int array1[lenght];
srand(time(0));
for ( int i = 0; i < lenght; i++) //populate array with random numbers and print them out
{
array1[i] = rand() % 3000;
cout << "Index " << i << " = " << array1[i] << endl;
}
findExtremes(array1, lenght); // call fn
return 0;
}
void findExtremes( const int array[], int size)
{
int maxV, minV, maxI, minI;
maxV = array[0];
minV = array[0];
minI = 0;
maxI = 0;
for ( int i = 1; i < size; i++)
{
if ( array[i] > maxV)
{
maxV = array[i];
maxI = i;
}
if ( array[i] < minV)
{
minV = array[i];
minI = i;
}
}
//find the number of occurances for min and max values
int minOcc = 0;
int maxOcc = 0;
for ( int i = 1; i < size; i++)
{
if (array[i] == minV)
minOcc++;
if (array[i] == minV)
maxOcc++;
}
//output
cout << "\nMinmim value is index " << minI << " with value " << minV << " and " << minOcc << " occurances" << endl;
cout << "\nMaxium value is index " << maxI << " with value " << maxV << " and " << maxOcc << " occurances" << endl << "\n";
}
For a start, they're actually pseudo random numbers, not random numbers. In any case, it may be that a a truly random sequence has that exact property that you're seeing :-) The sequence 1,1,1,1,1 is as equally likely to occur in a truly random set as much as 5,2,4,2,99.
If you want a "more random" random sequence, I wouldn't be using the normal ones shipped with C libraries (unless those libraries were written by people who understand randomness) - you should look into things like the Mersenne Twister, using /dev/random (if under Linux) and so on.
You may also want to look at this snippet of your code.
if (array[i] == minV)
minOcc++;
if (array[i] == minV)
maxOcc++;
I believe that last if should be comparing with maxV rather than minV. Otherwise there is zero chance that your minimum and maximum counts will be different.
When I make that change (and change % 3000 to % 30, to get a range of duplicates), I see:
Minmim value is index 112 with value 0 and 65 occurances
Maxium value is index 24 with value 29 and 58 occurances
And, not that it really matters in terms of this question, you may want to clean up your spelling somewhat:
lenght -> length.
minmum -> minimum
maxium -> maximum
occurances -> occurrences
I perform numerical simulations on Physics and my group uses the GSL library for that:
#include <gsl/gsl_rng.h>
#include <gsl/gsl_randist.h>
class Random
{
private:
gsl_rng* r; //!< Pointer to the gsl rng
public:
//! Constructor: uses argument as the seed
Random(long unsigned int seed);
long int R(int N);
long double R();
long double gaussianR(long double sigma);
};
inline Random::Random(long unsigned int s)
{
r = gsl_rng_alloc( gsl_rng_taus );
gsl_rng_set(r, s); //seed to use to the pseudo-aleatory number generator.
}
// a uniform number between 0 and N-1
inline long int Random::R(int N)
{
return gsl_rng_uniform_int (r, N);
}
// a uniform number between 0 and 1
inline long double Random::R()
{
return gsl_rng_uniform_pos( r );
}
// a gaussian distribution with sigma
inline long double Random::gaussianR(long double sigma)
{
return gsl_ran_gaussian(r, sigma);
}
you have to compile it with flags:
OTHER_LDFLAGS = -lgsl -lm -lgslcblas
and add includes and libs (this is for fink installation case):
HEADER_SEARCH_PATHS = /sw/include
LIBRARY_SEARCH_PATHS = /sw/lib
Hope this helps.
You can use the new random library included in C++11, or you can use the Boost::Random library that it was based off.
The behaviour of your Pseudo-Random Number Generator (PRNG) is perfectly normal.
In fact, if your draw enough numbers from rand(), you will always get the same extrema, since it is uniformly distributed.
In your case, the question is: do you need another behaviour? You should not pounce on True Random Numbers as #sehe suggests. This might be useless, and even problematic when dealing with stochastic simulations, which Monte Carlo algorithms are. Imagine that you want to debug a code snippet based upon random numbers, or that of colleague of yours intends to check your results: how would you do if you were not able to reproduce the same random sequence?
That is one of the reason why PRNGs are sufficient and often preferred when you do not need crypto-secure random numbers.
I think the problem is that your initial statement is wrong. The code is provides different numbers each time. I tried you unmodified code and there are the results:
Minmim value is index 1194 with value 0 and 1 occurances
Maxium value is index 1264 with value 2995 and 1 occurances
Minmim value is index 1958 with value 1 and 1 occurances
Maxium value is index 1510 with value 2991 and 1 occurances
...
However, there are two bugs in the code:
In the second for loop, you should start with i = 0.
You should compare with maxV instead of minV in the same loop.
With regards to the random number generation:
When seeded with the same number, a series of rand() calles should return the same numbers. rand() is not for random numbers, but for pseudo-random numbers. rand() should be have this way because than e.g. a simulation will output the same results when started with the same seed. It is a very nice property.
You seed it with the current time, which is ok and therefore rand() should return a different series of numbers each time (at least when not called multiple times a second). The seeding looks good to me. It is in fact very similar to the example provided here.
The sample size is 2000 and the range of generated numbers is 3000. This means that it is not probable that the minimal size and the maximal size are always the same. If the sample size would be a million, with a high probability 2999 should be the largest number in the very most runs.
Gentlepeople: NOTE
Yes! This answer is "old". And in the era of c++11, by all means use c++11 <random>. But please don't downvote this question, years after the fact because you think "Ew Everybody knows rand() is evil!". In fact, it is not. It's just limited, and very easy to use inappropriately. But - as an historic fact, it exists as an API and it is still useful to document how you can use it better. I'm not deleting this answer for very reason.
Original answer:
Please read
http://eternallyconfuzzled.com/arts/jsw_art_rand.aspx
Notably, don't write rand() % 3000. Write
int r = rand() / ( RAND_MAX / 3000 + 1 );
In fact, random should be uniformly distributed, meaning that indeed the lower and upper bound would have near 100% chance of occurring when the number of samples is large enough (larger than the size of the domain, for starters).
That's what true random is about (try to do a Monte-Carlo algorithm without it - you'd be very unhappy)