"Bertel Brander" <bertel@post4.tele.dk> wrote:
[8<8<8<]
> #include <stdlib.h>
#include <cstdlib>
er at foretrække, da den anden form er "depricated"
> #include <time.h>
#include <ctime>
[8<8<8<]
> int operator()(int range)
> { return rand()%range; }
Hvis vi antager at "rand" giver en jævn fordeling af tallene mellem 0 og
RAND_MAX og RAND_MAX er større end "range", så vil denne funktion _ikke_
give en jævn fordeling af tal mellem 0 og "range".
I stedet bør det være noget i retningen af
int operator()(int range)
{
if(range <= 0 || n > RAND_MAX)
throw domain_error("argument out of range");
const int bucket_size = RAND_MAX / range;
int r;
do r = rand() / bucket_size;
while (r >= range);
return r;
}
Se eventuelt
Accelerated C++
Andrew Koenig, Barbara E. Moo
ISBN 0-201-70353-X
side 135 for yderligere detaljer.
[8<8<8<]
> std::random_shuffle(Vector.begin(), Vector.end(), Rand);
Skal det ikke være
std::random_shuffle(Vector.begin(), Vector.end(), Rand());
hvor der faktisk bliver instantieret et "Rand" objekt ?
Bemærk at der findes 2 udgaver af random_shuffle:
* en hvor der bruges en default random generator
* en hvor man selv specificerer random generatoren
Er der nogen grund til at du gerne selv vil specificere random generatoren ?
Det forekommer mig at være nemmere at bruge default: det er både simplere at
bruge og man kan formode at default random generatoren giver en jævn
fordeling
[8<8<8<]
> Det forekommer mig at man burde kunne kalde random_shuffle
> med en funktion i stedet for en instans af en klasse
> som tredie argument.
Det skal være et funktions objekt, men der findes i C++ Standard Library
adaptere, der kan konveretere en "peger til funktion" til et funktions
objekt.
[8<8<8<]
> Er der nogen der har en løsning der:
> 1: Virker med de fleste kompilere
Den er lidt svær - hvad er "de fleste" ?
Jeg vælger at fortolke det upræcist som "moderne, almindeligt brugte
compilere som har implementeret C++ Standarden i rimelig grad". I den gruppe
finder vi på PC platformen f.eks. Microsoft Visual C++ .NET 2003, Intel C++
V7.0/V8.0, gcc 3.x og ofte Borland C++Builder V6.0.
Du har set Turbo C++ blive nævnt for nyligt har i gruppen, men den anser jeg
for at være så gammel at den er ligegyldig i denne sammenhæng. Visual C++
V6.0 hører til samme kategori, selvom den er fortsat er forholdsvis udbredt.
> 2: Overholder AnsiC++ standarden.
Det er oplagt.
Den simple version, som er testet med
Intel C++ for Windows V8.0
Microsoft Visual C++.NET 2003
Borland C++Builder V6.0
gcc 3.2 på Linux
og også oversat med
Comeau C/C++ 4.3.3
er
<C++ kode>
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std;
int main()
{
vector<int> all_numbers;
for(int i = 1; i != 90; ++i)
all_numbers.push_back(i);
random_shuffle(all_numbers.begin(), all_numbers.end());
copy(all_numbers.begin(), all_numbers.begin()+5,
ostream_iterator<int, char>(cout, " "));
}
</C++ kode>
Den lidt mere komplicerede model, hvor man specificerer random funktionen,
testet med
Intel C++ for Windows V8.0
Microsoft Visual C++ .NET 2003
men virker ikke med
gcc 3.2 på Linux
Borland C++Builder V6.0
Comeau C/C++ 4.3.3
er
<C++ kode>
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <stdexcept>
#include <functional>
#include <cstdlib>
using namespace std;
int nrand(int n)
{
if(n <= 0 || n > RAND_MAX)
throw domain_error("Argument to nrand is out of range");
const int bucket_size = RAND_MAX / n;
int r;
do r = rand() / bucket_size;
while (r >= n);
return r;
}
int main()
{
vector<int> all_numbers;
for(int i = 1; i != 90; ++i)
all_numbers.push_back(i);
random_shuffle(all_numbers.begin(), all_numbers.end(), ptr_fun(nrand));
copy(all_numbers.begin(), all_numbers.begin()+5,
ostream_iterator<int, char>(cout, " "));
}
</C++ kode>
For at få det til at virke med C++Builder, gcc og Comeau skal man ændre
random_shuffle(all_numbers.begin(), all_numbers.end(), ptr_fun(nrand));
til
pointer_to_unary_function<int, int> pnrand = ptr_fun(nrand);
random_shuffle(all_numbers.begin(), all_numbers.end(), pnrand);
eller på anden måde hjælpe med lave overload resolution, selvom jeg ikke
mener at det skulle være nødvendigt.
Det er klart grimmere, men dog er i overensstemmelse med C++ Standarden - og
opfylder dermed formodentligt dit ønske om at "virke med de fleste
compilere".
Venlig hilsen
Mogens Hansen