2016-06-16 18 views
9

Potrzebuję pomocy z procentem szansy w kodzie C#. Powiedzmy, że mam pętlę od 1 do 100, aw tej pętli mam kod "if", który chcę wykonać 70% razy (losowo). Jak to osiągnąć? Więc coś takiego:Implementacja "procentu szansy" w C#

static void Main(string[] args) 
{ 
    var clickPercentage = 70; 

    for (int i = 0; i < 100; i++) 
    { 
     if (chance) 
     { 
      //do 70% times 
     } 
    } 
} 

więc dla górnej przykład chciałbym jeśli kod na trafienie z szansą 70%, około 70 razy na moim przykładzie.

Co próbowałem: (nigdzie blisko 70%, bardziej jak 1 lub 2% szansy)

static void Main(string[] args) 
{ 
    var clickPercentage = 70; 

    for (int i = 0; i < 100; i++) 
    { 
     var a = GetRadnomNumber(1, clickPercentage); 
     var b = GetRadnomNumber(1, 101); 

     if (a <= b) 
     { 
      Console.WriteLine($"Iteracija {i} - {b} <= {a}"); 
     } 
    } 
} 

public static int GetRadnomNumber(int min, int max) 
{ 
    var random = new Random(); 
    var retVal = random.Next(min, max); 

    return retVal; 
} 
+1

Borderline duplikatem. Ty naprawdę musisz to przeczytać: http://stackoverflow.com/questions/767999/random-number-generator-only-generating-one-random-number – spender

+1

Proponuję zmienić twoją metodę z 'GetRadnomNumber' do 'GetRandomNumber' –

Odpowiedz

7

Użyj Random class.

Można użyć Random.Next(100) dostać losowy int między 0 i 99:

public static Random RandomGen = new Random(); 
..... 

int clickPercentage = 70; 
for (int i = 0; i < 100; i++) 
{ 
    int randomValueBetween0And99 = RandomGen.Next(100); 
    if (randomValueBetween0And99 < clickPercentage) 
    { 
     //do 70% times 
    } 
} 

To ważne, aby nie tworzyć losowe przykład w pętli bo to domyślny konstruktor wykorzystuje aktualny czas jako nasionko. To może spowodować powtarzanie wartości w pętli. Właśnie dlatego użyłem pola static. Można również przekazać instancję Random do metody, aby upewnić się, że wywołujący jest odpowiedzialny za okres istnienia i nasienie. Czasami ważne jest, aby użyć tego samego materiału siewnego, na przykład do powtórzenia tego samego testu.

2

Niezbyt pewna co do swojej logiki, ale z szybkiego spojrzenia tworzysz losowy obiekt w pętli.

Problem polega na tym, że klasa Random używa bieżącego czasu jako materiału siewnego. Jeśli materiał siewny jest taki sam, klasa Random wytworzy taką samą sekwencję liczb losowych. Ponieważ procesory te są naprawdę szybkie, zazwyczaj dzieje się tak, że kilka iteracji pętli będzie miało dokładnie to samo nasienie, a zatem wyjście generatora liczb losowych będzie całkowicie przewidywalne (i takie samo jak poprzednie).

Aby tego uniknąć, tylko utworzyć instancję klasy Random raz i używać go w kodzie, coś podobnego

private static readonly Random _rnd = new Random(); 
// use _rnd in you code and don't create any other new Random() instances 
+0

Czytałem tylko o przypadkowych instancjach i tak, miałem wiele takich samych" przypadkowych "liczb, które nie zdawały sobie sprawy, że to był problem. –

0

zasadzie nie potrzebujesz nowego Random -instance każdej iteracji. Proste użycie:

var r = new Random(); 

for(int i = 0; i < 100; i++) 
{ 
    var p = r.Next(100); 
    if (p >= 1 - myThreshhold) // do anything in 70% of cases 
} 

Alternatywnie można również użyć if (p <= myThreshold).

2

Owijanie go jako funkcję:

private static Random generator = null; 

/* 
* Calls onSuccess() chanceOfSuccess% of the time, otherwise calls onFailure() 
*/ 
public void SplitAtRandom(int chanceOfSuccess, Action onSuccess, Action onFailure) 
{ 
    // Seed 
    if (generator == null) 
     generator = new Random(DateTime.Now.Millisecond); 

    // By chance 
    if (generator.Next(100) < chanceOfSuccess) 
    { 
     if (onSuccess != null) 
      onSuccess(); 
    } 
    else 
    { 
     if (onFailure != null) 
      onFailure(); 
    } 
} 

i go używać:

for (int i = 0; i < 100; i++) 
{ 
    SplitAtRandom(70, 
       () => { /* 70% of the time */ }, 
       () => { /* 30% of the time */ }); 
}