Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » U++ Library support » U++ Core » random functions proposal
random functions proposal [message #35137] Mon, 16 January 2012 17:06 Go to next message
ratah is currently offline  ratah
Messages: 107
Registered: July 2010
Experienced Member
Hello everybody,

I looked for a random function between an interval (a,b) and did not find (maybe I am so pressed).
So, I decide to write these 2 functions c_random_a_b and upp_random_a_b for you.

#include <Core/Core.h>

using namespace Upp;

int putBetween(const int x1, const int x2, const int x3)
{
	int copie_x1 = x1;
	int copie_x2 = x2;
	
	
		
	// Put x3 between x1 et x2
	
	int d1 = x3 - copie_x1;
	int d2 = x3 - copie_x2;
	
	if(copie_x2 < copie_x1)
	{
		int tmp = copie_x2;
		
		copie_x2 = copie_x1;
		copie_x1 = tmp;
	}
	
	if(x3 >= copie_x1 && x3 <= copie_x2) return x3;
	
	if(d1 == 0) d1 = (copie_x2-copie_x1)/2;
		
	double rapport =  100*cos(d1+d2)*(copie_x2-copie_x1);
	if(rapport < 0) rapport *= -1;
	
	double dnewx3 = (100*copie_x1 + rapport)/100;
	int newx3 = (int) round(dnewx3);
	
	return newx3;
}

int c_rand_a_b(int x1, int x2)
{			
	
	// Using standard C function rand()
	
	if(x1 == x2)
		return x1;
				
	int x3 = rand();
	
	int newx3 = putBetween(x1, x2, x3);
	
	return newx3;
}


int upp_rand_a_b(int x1, int x2)
{			
	
	// Using U++ function Random()
	
	if(x1 == x2)
		return x1;
	
	String s3;
		
	dword dw3 = Random();
	s3 << dw3;
	
	int x3 = StrInt(s3);
	
	int newx3 = putBetween(x1, x2, x3);
	
	return newx3;
}

		
CONSOLE_APP_MAIN
{
	Cout() << "Random function proposal"; Cout().PutEol();
	
	int a, b;
	String sa, sb;
	
	do
	{
		Cout().PutEol();
		Cout() << "Enter a number named \"a\":";
	
		sa = ReadStdIn();	
		
		a = StrInt(sa);	
	}
	while(a<0);
	
	do
	{
		Cout().PutEol();
		Cout() << "Enter another number different of " << a << " named \"b\":";
	
		sb = ReadStdIn();
		
		b = StrInt(sb);		
	}
	while(b<0 || b==a);
	
	Cout().PutEol();
	Cout() << "--------------------------";
	
/// Proposal 1: c_rand_a_b(a,b)
	
			// To use c_rand_a_b correctly, you might reset srand each time you reexecute the program
			// Otherwise you get the same sequential data 
			
			Time t = GetSysTime();		
			srand((unsigned int) t.second*1000);
	
	Cout().PutEol();
	Cout() << "Using standard C rand() function : c_rand_a_b(" << a << ", " << b << ") ";
	Cout().PutEol();
	for(int i=0;  i<10; i++)
	{		
		Cout() << c_rand_a_b(a, b) << " ";
	}
	
/// Proposal 2: upp_rand_a_b(a,b)
	
	Cout().PutEol();
	Cout() << "Using U++ Random() function : upp_rand_a_b(" << a << ", " << b << ")";
	Cout().PutEol();
	for(int i=0;  i<10; i++)
	{
		Cout() << upp_rand_a_b(a, b) << " ";
	}
	
	Cout().PutEol();
}



If similar function does not exist yet, could you add this to UPP Core.

Thank you
Re: random functions proposal [message #35138 is a reply to message #35137] Mon, 16 January 2012 17:58 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1778
Registered: August 2008
Location: Czech Republic
Senior Contributor

Hi Ratah,

I have few comments Wink

First: I don't like the implementation of putBetween function. Cos() is too slow function to use for scaling. Also I admit I haven't really got the idea behind the scaling, as I was too lazy to think about it too much.

Second: Converting dword -> int using String is not a good idea Wink It will silence the compiler warnings, but still result into errors, because dword is unsigned 32 bit integer while int is signed 32bit integer (on most platforms), so the conversion will run into trouble when the dword is bigger then INT_MAX. Also the conversion through string is not efficient. In most cases you can probably just use simple cast: int(my_dword) and possibly check if the result is not negative.

Anyway short and simple solution to generate random number from given range is this:
int min=10;
int max=1000;
int rand = int(Random(max-min)+min); // you don't have to care about the range here as long as max < INT_MAX


I hope I haven't made any stupid mistake, as this all comes from the top of my head Smile

Best regards,
Honza
Re: random functions proposal [message #35139 is a reply to message #35137] Mon, 16 January 2012 18:31 Go to previous messageGo to next message
Sender Ghost is currently offline  Sender Ghost
Messages: 301
Registered: November 2008
Senior Member
Hello, ratah, dolik.rce.

ratah wrote on Mon, 16 January 2012 17:06


I looked for a random function between an interval (a,b) and did not find.


dolik.rce wrote on Mon, 16 January 2012 17:58


you don't have to care about the range here as long as max < INT_MAX


There is another implementation:
#include <Core/Core.h>

using namespace Upp;

// Returns Random from a to b, inclusively.
dword Random(dword a, dword b)
{
	if (a == b)
		return a;
	if (a < b)
		return a + Random(b - a + 1);
	return b + Random(a - b + 1);
}

CONSOLE_APP_MAIN
{
	const int n = 100;
	for (int i = 1, j = n; i <= n; ++i, --j)
		Cout() << Format("%3d, %3d: %s\n", i, j, AsString(Random(i, j)));
}

[Updated on: Mon, 16 January 2012 18:48]

Report message to a moderator

Re: random functions proposal [message #35146 is a reply to message #35139] Tue, 17 January 2012 09:56 Go to previous messageGo to next message
ratah is currently offline  ratah
Messages: 107
Registered: July 2010
Experienced Member
Thank you for your reply,

Dolik.rce, I aggree with you for the use of cos and dword conversion. The idea of scaling is because I do not know it is possible to pass a parameter to Random(). So I could not limit the max value I get with Random().

Dolik.rce, Sender Ghost, all of your solutions are OK.
Why not to introduce that usefull function into Core?

Best regards,

Ratah

[Updated on: Tue, 17 January 2012 10:21]

Report message to a moderator

Re: random functions proposal [message #35147 is a reply to message #35146] Tue, 17 January 2012 11:13 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12519
Registered: November 2005
Ultimate Member
ratah wrote on Tue, 17 January 2012 03:56

Thank you for your reply,

Dolik.rce, I aggree with you for the use of cos and dword conversion. The idea of scaling is because I do not know it is possible to pass a parameter to Random(). So I could not limit the max value I get with Random().

Dolik.rce, Sender Ghost, all of your solutions are OK.
Why not to introduce that usefull function into Core?

Best regards,

Ratah


I think that with Random(n), it is really not much useful to add second parameter.

BTW, what IS actually missing is double Randomf(); (returning 0 < x < 1) - but with all bells and whistles... which might be a little bit harder than it seems to be done correctly.
Re: random functions proposal [message #35151 is a reply to message #35147] Tue, 17 January 2012 12:58 Go to previous messageGo to next message
Sender Ghost is currently offline  Sender Ghost
Messages: 301
Registered: November 2008
Senior Member
Hello, Mirek.
mirek wrote on Tue, 17 January 2012 11:13


BTW, what IS actually missing is double Randomf(); (returning 0 < x < 1)


Something like this?
// Returns random value from 0 to 1 - 10^-9 with 10^-9 precision.
double Randomf()
{
	static const dword n = 1000000000;
	return double(Random(n)) / n;
}

[Updated on: Tue, 17 January 2012 13:01]

Report message to a moderator

Re: random functions proposal [message #35152 is a reply to message #35151] Tue, 17 January 2012 13:10 Go to previous messageGo to next message
koldo is currently offline  koldo
Messages: 3129
Registered: August 2008
Ultimate Member
Hello all

I think it would be good to have a double Randomf() function.

However random numbers have to be treated very seriously. It would be necessary to have a reliable Randomf() so IMHO an implementation based in dword Random() would not be good.


Best regards
IƱaki
Re: random functions proposal [message #35154 is a reply to message #35151] Tue, 17 January 2012 13:59 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12519
Registered: November 2005
Ultimate Member
Sender Ghost wrote on Tue, 17 January 2012 06:58

Hello, Mirek.
mirek wrote on Tue, 17 January 2012 11:13


BTW, what IS actually missing is double Randomf(); (returning 0 < x < 1)


Something like this?
// Returns random value from 0 to 1 - 10^-9 with 10^-9 precision.
double Randomf()
{
	static const dword n = 1000000000;
	return double(Random(n)) / n;
}



Yes, but that 10^-9 is perahps not enough. We have 56 bits to fill...

Sure, it is enough for most applications, but so far I believe not good enough as addition to library. Especially if it is such one-liner.
Re: random functions proposal [message #35156 is a reply to message #35154] Tue, 17 January 2012 14:24 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 12519
Registered: November 2005
Ultimate Member
...but it looks like int64 -> double conversion is CPU opcode, so perhaps Random64(int n) as prerequisite, than Randomf() is a good path...
Re: random functions proposal [message #35158 is a reply to message #35137] Tue, 17 January 2012 18:45 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1778
Registered: August 2008
Location: Czech Republic
Senior Contributor

Looking for the details of floating point RNGs, I found this: http://allendowney.com/research/rand/. This pseudo scientific paper seems to propose reasonably simple algorithm that overcomes the obvious problems of the implementation Sender Ghost proposed. Only problem I see that the code linked on this page is GPL3 licensed... But even if we don't use it, the explanation about why using Random()/RAND_MAX is bad is worth reading Wink

Honza
Re: random functions proposal [message #35159 is a reply to message #35158] Tue, 17 January 2012 20:08 Go to previous messageGo to next message
Sender Ghost is currently offline  Sender Ghost
Messages: 301
Registered: November 2008
Senior Member
dolik.rce wrote on Tue, 17 January 2012 18:45

This pseudo scientific paper seems to propose reasonably simple algorithm that overcomes the obvious problems of the implementation Sender Ghost proposed.


Well, what I "proposed" (and I didn't propose, but just showed a simple solution) is useful for float numbers, not double, hence this Randomf, instead of Randomd, I think.
With qword Random64(qword n) it will be possible to do the same, of course.

mirek wrote on Tue, 17 January 2012 14:24

...but it looks like int64 -> double conversion is CPU opcode, so perhaps Random64(int n) as prerequisite, than Randomf() is a good path...

According to "Random number generators discussion" it is possible to combine two random dword values (MAKEQWORD macro might be useful here) to get random qword value.

qword Random64()
{
	return MAKEQWORD(Random(), Random());
}

qword Random64(qword n)
{
	qword mask = n, r;
	mask |= mask >> 1;	mask |= mask >> 2;
	mask |= mask >> 4;	mask |= mask >> 8;
	mask |= mask >> 16;	mask |= mask >> 32;

	do
		r = Random64() & mask;
	while(r >= n);
	return r;
}

qword Random64(qword a, qword b)
{
	if (a == b)
		return a;
	if (a < b)
		return a + Random64(b - a + 1);
	return b + Random64(a - b + 1);
}


Edit: Added possible Random64 implementation(s).

[Updated on: Tue, 17 January 2012 23:23]

Report message to a moderator

Re: random functions proposal [message #35160 is a reply to message #35159] Tue, 17 January 2012 20:25 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1778
Registered: August 2008
Location: Czech Republic
Senior Contributor

Sender Ghost wrote on Tue, 17 January 2012 20:08


Well, what I "proposed" (and I didn't propose, but just showed a simple solution) is useful for float numbers, not double, hence this Randomf, instead of Randomd, I think.
With qword Random64(qword n) it will be possible to do the same, of course.

mirek wrote on Tue, 17 January 2012 14:24

...but it looks like int64 -> double conversion is CPU opcode, so perhaps Random64(int n) as prerequisite, than Randomf() is a good path...

According to "Random number generators discussion" it is possible to combine two random dword values (MAKEQWORD macro might be useful here) to get random qword value.

The type doesn't really matter, I referred to "float" just as a sloppy abbreviation for "floating point type". The problem is that even with qword the simple division will not generate uniform distribution because floating point numbers are not equally spaced (as is explained in the document I linked to).

Honza
Re: random functions proposal [message #35161 is a reply to message #35160] Tue, 17 January 2012 20:37 Go to previous messageGo to next message
Sender Ghost is currently offline  Sender Ghost
Messages: 301
Registered: November 2008
Senior Member
dolik.rce wrote on Tue, 17 January 2012 20:25

The type doesn't really matter, I referred to "float" just as a sloppy abbreviation for "floating point type". The problem is that even with qword the simple division will not generate uniform distribution because floating point numbers are not equally spaced (as is explained in the document I linked to).

The article shows, that there is more range for float numbers, than just using sufficient range. I agree, there is more range. Therefore, the function has limitations, which described in the comment for it.
Re: random functions proposal [message #35170 is a reply to message #35161] Wed, 18 January 2012 15:44 Go to previous messageGo to next message
cbpporter is currently offline  cbpporter
Messages: 1400
Registered: September 2007
Senior Contributor
What Random needs is the ability to give it a seed. So you can produce the same sequence of numbers twice. Or is there already support for this?
Re: random functions proposal [message #35171 is a reply to message #35170] Wed, 18 January 2012 17:45 Go to previous messageGo to next message
dolik.rce is currently offline  dolik.rce
Messages: 1778
Registered: August 2008
Location: Czech Republic
Senior Contributor

cbpporter wrote on Wed, 18 January 2012 15:44

What Random needs is the ability to give it a seed. So you can produce the same sequence of numbers twice. Or is there already support for this?

These functions should be able to do that:
void SeedRandom(dword *seed,int len){
	if(!sRng) {
		sRng = new(sRb) MTrand;
	}
	sRng->init_by_array(seed,len);
}

void SeedRandom(dword Seed){
	if(!sRng) {
		sRng = new(sRb) MTrand;
	}
	sRng->init_genrand(Seed);
}

But I didn't have the time to test it Wink

Honza
Re: random functions proposal [message #35172 is a reply to message #35171] Wed, 18 January 2012 19:24 Go to previous message
mirek is currently offline  mirek
Messages: 12519
Registered: November 2005
Ultimate Member
Random64 and SeedRandom now in Core.

I have also added "trivial" implementation of Randomf.

Mirek
Previous Topic: Init a ctrl inside INITBLOCK
Next Topic: problem with new and delete
Goto Forum:
  


Current Time: Thu Jun 04 07:17:49 CEST 2020

Total time taken to generate the page: 0.00978 seconds