Toon posts:

[VB] Randomize, niet 2 keer hetzelfde getal

Pagina: 1
Acties:
  • 422 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Ik moet voor school een project maken waarmee ik 10 cijfers tussen de 1 en 25 moet laten verzinnen.
Dit doe ik via randomize functie (logisch), maar nu werkt het allemaal wel alleen krijg ik vaak 2 dezelfde getallen, wat ook wel logisch is.
Maar ik heb al verschillende manieren geprobeerd om het op te lossen (listbox.list( ), if i = i etc)
Het wil tot nu toe niet lukken.
Heeft iemand een stukje code en/of tips zodat ik dit kan laten werken.
Ik gebruik visual basic 6.0
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
Private Sub start_Click()

listbox.Clear 'leeg maken nrbox

Randomize  ' Initialize random-number generator.

For i = 1 To 10 'loop

    listbox.AddItem CInt(Rnd * 24) + 1 ' zet het in de list        

Next
   
End Sub

[ Voor 3% gewijzigd door Verwijderd op 25-04-2007 10:48 ]


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 20:39

gorgi_19

Kruimeltjes zijn weer op :9

De Random buiten de loop zetten; een Random zal verder wel een Next() method oid hebben en die gebruiken. Een random maakt intern namelijk gebruik van de tijd; bij zo een kleine tijdspanne in een for-loop is het verschil 0, waardoor je 2x hetzelfde getal krijgt.

Digitaal onderwijsmateriaal, leermateriaal voor hbo


  • truegrit
  • Registratie: Augustus 2004
  • Laatst online: 19-11 23:52
gewoon elke gevonden waarde in een lijst zetten zoals je zegt te doen, dan per iteratie de lijst afgaan of hij er in zit, indien dit het geval is een nieuwe verzinnen en dan weer de lijst afgaan, etc, etc totdat je een nieuwe waarde hebt die dus niet in de lijst zit.

lijkt me niet zo moeilijk toch?

hallo


  • BtM909
  • Registratie: Juni 2000
  • Niet online

BtM909

Watch out Guys...

offtopic:
Code kan ook een taal bevatten, dus [code=vb][/code] ;)


Overigens als ik ga [google=Visual Basic unique random numbers] dan vind ik genoeg relevante hits. Wellicht dat dat je verder kan helpen :)

Ace of Base vs Charli XCX - All That She Boom Claps (RMT) | Clean Bandit vs Galantis - I'd Rather Be You (RMT)
You've moved up on my notch-list. You have 1 notch
I have a black belt in Kung Flu.


  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 20:39

gorgi_19

Kruimeltjes zijn weer op :9

truegrit schreef op woensdag 25 april 2007 @ 10:49:
gewoon elke gevonden waarde in een lijst zetten zoals je zegt te doen, dan per iteratie de lijst afgaan of hij er in zit, indien dit het geval is een nieuwe verzinnen en dan weer de lijst afgaan, etc, etc totdat je een nieuwe waarde hebt die dus niet in de lijst zit.

lijkt me niet zo moeilijk toch?
Dan kan je dus net zo goed een sleep van 1 ms gebruiken ;)

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Verwijderd

Topicstarter
truegrit schreef op woensdag 25 april 2007 @ 10:49:
gewoon elke gevonden waarde in een lijst zetten zoals je zegt te doen, dan per iteratie de lijst afgaan of hij er in zit, indien dit het geval is een nieuwe verzinnen en dan weer de lijst afgaan, etc, etc totdat je een nieuwe waarde hebt die dus niet in de lijst zit.

lijkt me niet zo moeilijk toch?
zoiets had ik ook bedacht ja, maar ik ben nogal een beginner hiermee.
dus het echt coden gaat nog niet van harte.
maar ik ga jou manier proberen, bedankt :)

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 01:48

Reptile209

- gers -

Een mogelijke andere aanpak is de volgende:
Maak een array met de getallen 1-25 erin. Doorloop een lus waarin je - bijvoorbeeld 100x - 2 willekeurige plaatsen van de array met elkaar verwisselt. Omdat je dat vaak (100x) doet, wordt je array redelijk "geschud". Pak vervolgens de plaatsen 1 t/m 10 uit je array als uitkomst.
Experimenteer even met die 100, misschien heb je meer nodig om goed te schudden.

Het voordeel hiervan is, dat je niet hoeft te klooien met het feit dat er voor het 10e getal nog maar 16 geldige waarden over zijn, waardoor de statistiek er niet beter op wordt.

Zo scherp als een voetbal!


  • Oscar Mopperkont
  • Registratie: Februari 2001
  • Laatst online: 03-08-2024

Oscar Mopperkont

Hoepel op!

Maak een array waarin de getallen van 1 tot 25 staan en ga die hutselen en neem de eerste 10 getallen, heb je nooit twee keer hetzelfde getal.

Edit: Reptile209 was mij net een fractie voor...

[ Voor 15% gewijzigd door Oscar Mopperkont op 25-04-2007 11:00 ]


  • Sallin
  • Registratie: Mei 2004
  • Niet online
Als het allemaal unieke getallen moeten zijn kan je een vector aanmaken waar alle mogelijke getallen instaan en dan een random plek uit die vector kiezen waarbij je die positie direct verwijderd. Dit is volgens mij sneller dan kijken of je hem al hebt.

edit: vergelijkbaar, maar net anders als mijn twee bovenburen :). Sowieso grappig hoeveel oplossingen er zijn voor zo'n "probleem".

[ Voor 20% gewijzigd door Sallin op 25-04-2007 11:02 ]

This too shall pass
Debian | VirtualBox (W7), Flickr


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Reptile209 schreef op woensdag 25 april 2007 @ 10:58:
Een mogelijke andere aanpak is de volgende:
Maak een array met de getallen 1-25 erin. Doorloop een lus waarin je - bijvoorbeeld 100x - 2 willekeurige plaatsen van de array met elkaar verwisselt. Omdat je dat vaak (100x) doet, wordt je array redelijk "geschud". Pak vervolgens de plaatsen 1 t/m 10 uit je array als uitkomst.
Experimenteer even met die 100, misschien heb je meer nodig om goed te schudden.
Persoonlijk ben ik niet zo'n voorstander van op zo'n manier schudden... Zeker bij een klein aantal shuffles is het resultaat geen uniforme verdeling. Ik denk dat het handiger is om gewoon 10 willekeurig elementen uit de lijst te pakken, een trekking zonder teruglegging dus :). Begin weer met de array van de 25 elementen, pak er een willekeurige uit (rnd*N) en verwissel 'm met het eerste element in de lijst. Je eerste element is nu random. Pak dan weer een willekeurige uit de rest (rnd*(N-1) + 1), verwissel 'm met de tweede, en nu zijn je eerste 2 elementen random. Doe dat 10 keer, en je hebt 10 willekeurige en bovendien uniform verdeelde (voor zover je random number generator dat ook is natuurlijk) getallen.

C++:
1
2
3
4
5
6
7
8
9
void shuffle(std::vector<int> & elements, int numElems)
{
    for (int index = 0; index < numElems; index++)
    {
        int elemsLeft = elements.size() - index;
        int pos = index + rand() % elemsLeft;
        std::swap(elements[index], elements[pos]);
    }
}


Overigens heeft C++ std::random_shuffle, die precies dit doet voor willekeurige (random access) iterators ;)

[ Voor 21% gewijzigd door .oisyn op 25-04-2007 11:50 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 01:48

Reptile209

- gers -

.oisyn schreef op woensdag 25 april 2007 @ 11:25:
[...]

Persoonlijk ben ik niet zo'n voorstander van op zo'n manier schudden... Zeker bij een klein aantal shuffles is het resultaat geen uniforme verdeling.
_/-\o_
Uitstekend gejat! Hetgeen ik riep heb ik vroegâh ooit eens "uit mijn mouw geschud" voor een simpel kaartspelletje. Jouw voorstel is duidelijk, statistisch verantwoord en bovendien onbeperkt schaalbaar. Het enige dat de TS er aan toe moet voegen zijn 1 of 2 regeltjes commentaar om over een half jaar nog te weten hoe het werkt. * Reptile209 gaat 'm onthouden ;).

Zo scherp als een voetbal!


  • b19a
  • Registratie: September 2002
  • Niet online
Je zou ook nog de nummers 1 t/m 25 in een array kunnen zetten en dan 10x willekeurig een nummer eruit halen (dus ook verwijderen uit je array), zodat je uiteindelijk nog 15 nummers in je beginarray hebt en 10 in je resultaatarray.

edit:
Ongeveer wat .oisyn zegt dus, alleen houdt hij de getallen in 1 array en bovenstaande methode geeft je 2 arrays

[ Voor 21% gewijzigd door b19a op 26-04-2007 10:42 ]


  • Dido
  • Registratie: Maart 2002
  • Laatst online: 01-12 13:02

Dido

heforshe

Met als subtiel verschil dat je de lege plaatsen in de je erste array moet "opvullen" om geen dubbelen te krijgen ;)

Wat betekent mijn avatar?


  • YakuzA
  • Registratie: Maart 2001
  • Niet online

YakuzA

Wat denk je nou zelluf hey :X

Binnen VB.Net gebruik ik altijd de volgende manier waar ik nog geen problemen bij ben tegengekomen
(uiteraard gestripte versie)

code:
1
2
3
4
5
6
7
8
9
Public Class dinges
 Dim Randomizer As New Random()

Public Function getNextRandom(Byval Max as Integer) As Integer
   Return Randomizer.Next(Max)
End Function


End Class


Denk dat ze dus wel wat veranderd hebben van 6.0 naar .net :)

[ Voor 9% gewijzigd door YakuzA op 26-04-2007 13:11 ]

Death smiles at us all, all a man can do is smile back.
PSN


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Heb je de draad überhaupt gelezen of begrijp je hem gewoon niet? :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 04:07
Reptile209 schreef op woensdag 25 april 2007 @ 10:58:
Een mogelijke andere aanpak is de volgende:
Maak een array met de getallen 1-25 erin. Doorloop een lus waarin je - bijvoorbeeld 100x - 2 willekeurige plaatsen van de array met elkaar verwisselt. Omdat je dat vaak (100x) doet, wordt je array redelijk "geschud".
Dat valt dus behoorlijk tegen. Je moet namelijk behoorlijk vaak schudden om een beetje in de buurt te komen van een nette kansverdeling; 100 lijkt me erg weinig, maar is al wel ruim vier keer meer elementen verwisselen dan nodig. Al met al is het dus een waardeloze methode om te schudden: traag en slecht.

Doe het dus gewoon altijd met een variant op de code oisyn ook geeft. Dat is 100% correct (gelijke kans op elke mogelijk permutatie) en heel snel (N-1 swaps voor een lijst van N elementen). Overigens geeft het kiezen van een integer in [0,N) met rand()%N ook geen gelijke kansen, maar soit.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Een methode om een [0,M) int te mappen op een uniforme [0,N) range:

C++:
1
2
3
4
5
6
7
8
9
10
11
int better_rand(int num)
{
    int leftOver = RAND_MAX % num + 1;
    if (leftOver == num)
        leftOver = 0;
    int thresshold = RAND_MAX - leftOver;

    int r;
    do r = rand(); while (r > thresshold);
    return r % num;
}


Nou heeft elk getal wel evenveel kans (op voorwaarde dat rand() echt uniform verdeeld is)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Philip J. Dijkstra
  • Registratie: Februari 2000
  • Laatst online: 30-11 16:25
Alsjeblieft, dit is mn Access VB code:
Moet niet al te moeilijk zijn om om te schrijven naar VB.NET



code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
'-- Declareer dit global --
    Dim Aantal_Regels_Array() As Boolean
    Dim Teller As Integer
    Dim RandomGetal As Integer

'-- Daar waar dingen met het getal gaat doen --
    Teller = 25
    ReDim Aantal_Regels_Array(Teller)

x = 1
While x <= Teller
    strWhatever = KiesGetal()
    '---
    // Doe dingen met je random nummer
    '---
    x += 1
Wend

'-- De daadwerkelijke random functie --
Public Function KiesGetal() As Integer

Randomize

Nogmaals:
    RandomGetal = Int(Rnd * Teller)
    '-- Kies net zo lang random nummers totdat we 1 tegen komen die we nog niet eerder gebruikt hebben.
    If Aantal_Regels_Array(RandomGetal) = True Then
        GoTo Nogmaals
    Else
        Aantal_Regels_Array(RandomGetal) = True
        KiesGetal = RandomGetal
    End If
End Function



  • Philip J. Dijkstra
  • Registratie: Februari 2000
  • Laatst online: 30-11 16:25
Oh, ik lees net dat je 10 getallen moet pakken:

While x <= Teller

Moet zijn

While x <= 10

--edit--
Sorry mensen, het is te warm op kantoor, ik had mn vorige bericht moeten aanpassen ipv een nieuwe te posten. Excuus.

[ Voor 39% gewijzigd door Philip J. Dijkstra op 26-04-2007 15:46 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Wat dus ongelooflijk slecht performt, zeker voor grote ranges, aangezien je bijvoorbeeld bij 10.000 elementen zit te wachten tot je random functie eindelijk eens dat ene element oplevert, met een kans van 0.01%

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 23:31

.oisyn

Moderator Devschuur®

Demotivational Speaker

Soultaker schreef op donderdag 26 april 2007 @ 14:50:
[...]

Dat valt dus behoorlijk tegen. Je moet namelijk behoorlijk vaak schudden om een beetje in de buurt te komen van een nette kansverdeling; 100 lijkt me erg weinig
Overigens valt 100 keer schudden voor een array van 25 wel mee, het is aardig uniform. Volgens mijn meting dan, waar wellicht wat op aan te merken is. Ik heb een test gemaakt waarin ik 10.000 keer een array van N opeenvolgende elementen in de range [0,N) met verschillende methoden door elkaar schud, en vervolgens tel ik van alle elementen de afstand tot hun oorspronkelijke plek bij elkaar op, om een index te vormen van hoe goed er geschud is. Tot slot bereken ik nog de verwachte index van een ideaal uniform verdeelde shuffle (het gemiddelde van wat je zou krijgen als je alle permutaties af zou lopen)

Dit zijn mijn resultaten voor een array van 25 elementen:
code:
1
2
3
4
5
6
7
8
9
       expected: 208.000
     randperm(): 208.336 (time: 0.016s)
    shuffle(10): 117.457 (time: 0.016s)
    shuffle(25): 182.266 (time: 0.047s)
    shuffle(50): 204.983 (time: 0.094s)
   shuffle(100): 207.516 (time: 0.156s)
   shuffle(400): 208.729 (time: 0.687s)
  shuffle(1000): 207.969 (time: 1.579s)
 shuffle(10000): 208.021 (time: 14.109s)

randperm() is mijn implementatie, shuffle(10) is Reptile's voorstel met 10x shufflen, etc.. Na 100 keer ben je er dus al aardig, maar het scheelt wel een factor 10 kwa tijd :). Merk ook op dat shuffle(25) half zo snel is als randperm(), omdat je per swap 2 random nummers nodig hebt.

Wat ik overigens wel frappant vindt is dat iig shuffle(10000), maar shuffle(1000) ook wel, de expected value altijd dichter benadert dan randperm(), wat volgens mij te maken heeft met het feit dat ik gewoon rand() % N doe ipv de better_rand(N) functie die ik eerder voorstelde. Even proberen of dat uitmaakt :)

.edit: hmm, niet echt
code:
1
2
3
4
5
6
7
8
9
10
       expected: 208.000
     randperm(): 208.148 (time: 0.015s)
    randperm2(): 208.107 (time: 0.016s)
    shuffle(10): 117.677 (time: 0.015s)
    shuffle(25): 182.388 (time: 0.032s)
    shuffle(50): 205.140 (time: 0.093s)
   shuffle(100): 208.279 (time: 0.141s)
   shuffle(400): 208.341 (time: 0.656s)
  shuffle(1000): 208.205 (time: 1.297s)
 shuffle(10000): 208.280 (time: 12.594s)

Maar ik zie nu ook uitschieters voor de grote shuffles, dus wellicht was het gewoon toeval ;)

[ Voor 13% gewijzigd door .oisyn op 26-04-2007 17:09 . Reden: code tag leest prettiger dan cmd tag ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Mischa_NL
  • Registratie: Mei 2004
  • Laatst online: 01-02-2023
en daarnaast: hoe kun je die school serieus nemen als ze vb 6 onderwijzen?!

Kan het on-topic en zonder gezever? Waar gaat dit over :? Als je iets te melden hebt post dan gerust, maar heb je niks te zeggen: post dan ook niks :|

[ Voor 57% gewijzigd door RobIII op 26-04-2007 17:45 ]


Verwijderd

Topicstarter
Mischa_NL schreef op donderdag 26 april 2007 @ 17:38:
en daarnaast: hoe kun je die school serieus nemen als ze vb 6 onderwijzen?!
[mbr]
Kan het on-topic en zonder gezever? Waar gaat dit over :? Als je iets te melden hebt post dan gerust, maar heb je niks te zeggen: post dan ook niks :|
[/]
het is als basis, heb voor de rest nog nooit geprogrammeerd dus vandaar ;)

iedereen bedankt :) ik ga het allemaal even proberen (heb nu wel vakantie, maar vast wel wat vrije tijd ;)) want was er nog niet helamaal uit gekomen.
Pagina: 1