2009-08-31 10 views
6

Próbuję losowo generować liczbę dodatnią lub ujemną, a następnie martwić się o większy zakres Mam nadzieję, że losowo wygenerować 1 lub -1, aby po prostu pomnożyć przez moje inne losowe numer.Cel C - Losowe wyniki to 1 lub -1

Wiem, że można to zrobić za pomocą dłuższej reguły generowania 0 lub 1, a następnie sprawdzenia zwrotu i użycia tego do pomnożenia przez 1 lub -1.

Mamy nadzieję, że ktoś wie o łatwiejszym sposobie losowego ustawienia znaku na numerze. Staram się, aby mój kod był jak najbardziej czysty.

Odpowiedz

22

Lubię używać arc4random() ponieważ nie wymaga do materiału siewnego generator liczb losowych. Dogodnie zwraca również wartość uint_32_t, więc nie musisz się martwić, że wynik wynosi od 0 do 1, itd. Po prostu podasz losową liczbę całkowitą.

int myRandom() { 
    return (arc4random() % 2 ? 1 : -1); 
} 
+0

+1 dla prostego i prostego. –

+0

Bardzo inteligentny, dzięki! – kubilay

10

Jeśli dobrze rozumiem pytanie, chcesz sekwencji pseudolosowych 1 i 1:

int f(void) 
{ 
     return random() & 1 ? 1 : -1; 
    // or... 
    // return 2 * (random() & 1) - 1; 
    // or... 
    // return ((random() & 1) << 1) - 1; 
    // or... 
    // return (random() & 2) - 1; // This one from Chris Lutz 
} 

Aktualizacja: Ok, coś zostało przeszkadza mi to, ponieważ pisałem. Jedną z częstych słabości typowych RNG jest to, że bity niskiego rzędu mogą przechodzić przez krótkie cykle. To chyba najlepiej przetestować trochę wyższego rzędu:     random() & 0x80000 ? 1 : -1

+5

Dlaczego nie '(random() i 2) - 1 '? –

+2

Przypomnienie dla tych, którzy nie znają liczb losowych generowanych przez system deterministyczny - nie są przypadkowi. Prawdopodobnie będziesz chciał wywołać 'srandomdev();' w pewnym wygodnym punkcie "uruchomienia aplikacji". Musisz zadzwonić tylko raz. Spowoduje to wygenerowanie generatora liczb losowych ze źródłem względnie losowych bitów, więc wyniki z 'random()' są "bardziej losowe". W przeciwnym razie 'random()' zaczyna się od dokładnie tego samego za każdym razem. – johne

+0

Zakładając, że mówimy o 'Xcode.app'/standardowej aplikacji Cocoa, najbardziej oczywistym miejscem do połączenia z' srandom() 'jest plik' main.m' podany w pliku 'Xcode.app', funkcja 'main()', tuż przed wywołaniem 'NSApplicationMain()'. – johne

0

Aby wygenerować 1 lub -1 bezpośrednio, można zrobić:

int PlusOrMinusOne() { 
    return (rand() % 2) * 2 - 1 
} 

Ale dlaczego jesteś zaniepokojony szerszym zakresie?

+0

Rand() ma pewne problemy. może należy rozważyć użycie czegoś innego. http://ianbullard.squarespace.com/journal/2009/4/28/why-you-should-never-never-rand.html – neoneye

-1

Ten dodatkowy krok nie daje żadnej dodatkowej "losowości". Po prostu wygeneruj swój numer od razu w zakresie, który potrzebujesz (np. -10..10). Standard rand() zwróci wartość z tego zakresu: 0..1 Możesz pomnożyć ją przez stałą, aby zwiększyć rozpiętość zakresu lub możesz dodać stałą, aby przesunąć ją w lewo/w prawo na osi X. E.g. do generowania losowych wartości od od (-5..10) Zakres trzeba będzie: rand() * 15-5

+0

@johne - Myślę, że Dmitry myli Javę z ObjectiveC ... –

+0

Przepraszamy za zamieszanie. Nie miałem na myśli konkretnego języka, ale raczej funkcję ogólną, która zwraca wartość losową (zmiennoprzecinkową) z zakresu 0..1. Moim głównym celem było wyjaśnienie, w jaki sposób przekształcić go na jakikolwiek inny zakres (tj. Że nie potrzebujesz tej -1 lub 1 wartości losowej wygenerowanej) – DmitryK

-1

rand daje liczbę od 0 do RAND_MAX który obejmie każdy kawałek w int wyjątkiem Znak. Przesuwając wynik o 1 bit, zamieniasz podpisany MSB na znak, ale wyzerowałeś bit, który możesz ponownie zaludnić losowym bitem z innego połączenia do rand. Kod będzie wyglądać następująco:

int my_rand() 
{ 
    return (rand() << 1) + (rand() & 1); 
} 
+1

-1 dla nadmiernego komplikowania prostego problemu Objective-C z niepotrzebnie złożonym C++. Zwykle nie dbałbym o to, aby takie problemy zostały odrzucone, ale biblioteka standardowa C ma doskonale dobre funkcje liczb losowych, które nie wymagają ciągnięcia w języku C++, co może mieć dość nieprzyjemne efekty uboczne i komplikować kompilację, środowisko wykonawcze itp. –

+0

Wyciągnąłem std :: namespace, więc jest to teraz poprawne C. 'std :: rand' jest tym samym' rand'em C, po prostu chronionym za przestrzenią nazw 'std', aby uniknąć kolizji. – fbrereto

0
return (((arc4random() & 2) * 2) - 1);