Probleme beim Zufalls-Punkte erzeugen [gelöst]

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Probleme beim Zufalls-Punkte erzeugen [gelöst]

Beitrag von heinz » 04.01.2019 21:54:18

Hallo Zusammen,

erstmal wuensche ich Euch allen ein gutes neues Jahr!


Hier nun mein derzeitiges Problem, zu dem ich ein paar Anregungen gebrauchen koennte:

Ich erzeuge mit einem C-Code dieser Art:

Code: Alles auswählen

for(int z=0 ; z<10000 ; z++)
{
  float winkel= (float) (rand()% 36000000) / 100000.0;
  float radius= (rand()% 2000) / 10.0;
  float x = sin( winkel * (Pi / 180.0) ) * radius;
  float y = cos( winkel * (Pi / 180.0) ) * radius;
}
Zufalls-Positionen (y,x), die zusammen eine runde Scheibe ergeben sollten.

Leider sind die Positionen nicht richtig gleichmaessig verteilt
sondern es entsteht eine Art Kreuz.
1993

Kann mir jemand sagen warum dem so ist?

Vielen Dank schonmal.

Gruss, Heinz
Zuletzt geändert von heinz am 23.01.2019 19:52:19, insgesamt 4-mal geändert.

Benutzeravatar
schorsch_76
Beiträge: 2597
Registriert: 06.11.2007 16:00:42
Lizenz eigener Beiträge: MIT Lizenz

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von schorsch_76 » 04.01.2019 22:33:57

Hallo,

dir auch ein gutes neues Jahr!

rand() erzeugt keine guten Zufallszahlen. Es ist ein schlechter Pseudo RNG. Probier /dev/urandom ;) Lese 4 Bytes in einen int ein und mach dann modulo.

Benutzeravatar
MSfree
Beiträge: 11604
Registriert: 25.09.2007 19:59:30

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von MSfree » 04.01.2019 22:43:10

Ich denke, daß das Problem im Modulus-Operator liegt.

rand() liefert eine gleichmässig verteilte Zufallszahl zwischen 0 und RAND_MAX, RAND_MAX ist auf meinem System als 2³¹-1 definiert. Wenn du nun immer den Modulus von der Zufallszahl nimmst, kann das Ergebnis nicht gleichverteilt sein.

Ich würde es mal folgendermassen Umsetzen:

Code: Alles auswählen

float MyRandom( float Bereich )
{
  float rNum = ( (float) rand() / (float) RAND_MAX ) * Bereich;
  returnn rNum;
}

for(int z=0 ; z<10000 ; z++)
{
  float winkel= MyRandom( 360.0 );
  float radius= MyRandom( 200.0 );
  float x = sin( winkel * (Pi / 180.0) ) * radius;
  float y = cos( winkel * (Pi / 180.0) ) * radius;
}
Es gibt alternativ auch noch andere Zufallsfunktionen, die Direkt z.B. ein double zwischen 0.0 und 1.0 liefern, siehe auch man drand48. (eventuell brauchst du dazu apt-get install manpages-de-dev)

Benutzeravatar
hikaru
Moderator
Beiträge: 13900
Registriert: 09.04.2008 12:48:59

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von hikaru » 04.01.2019 22:45:30

Vollständig erklären kann ich das Phänomen nicht, aber was mathematisch passiert ist, dass in deiner Polarkoordinatentransformation der Term für die Winkelfunktionen ( winkel * (Pi / 180.0) ) überdurchschnittlich häufig Werte nahe Null und Eins annimmt.

Du hast noch einen zweiten systematischen, vermutlich ungewollten Effekt:
Deine Puntwolke ballt sich in der Mitte. Die Ursache ist, dass die Punkte gleichmäßig auf dem Radius verteilt sind. Für eine gleichmäßige Dichte in der Fläche musst du dafür sorgen, dass deine Punkte gleichmäßig auf dem Quadrat des Radius' verteilt sind.

Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von heinz » 04.01.2019 22:48:24

Hallo schorsch,
schorsch_76 hat geschrieben: ↑ zum Beitrag ↑
04.01.2019 22:33:57
dir auch ein gutes neues Jahr!
Danke!
schorsch_76 hat geschrieben: ↑ zum Beitrag ↑
04.01.2019 22:33:57
rand() erzeugt keine guten Zufallszahlen. Es ist ein schlechter Pseudo RNG. Probier /dev/urandom ;) Lese 4 Bytes in einen int ein und mach dann modulo.
Danke fuer den Hinweis.
Kennst Du da schon was fertiges was man einfach Einbinden kann?
Oder lieber selbermachen?

Gruss heinz

Benutzeravatar
schorsch_76
Beiträge: 2597
Registriert: 06.11.2007 16:00:42
Lizenz eigener Beiträge: MIT Lizenz

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von schorsch_76 » 04.01.2019 23:00:49

https://stackoverflow.com/questions/822 ... m-int-in-c

"Don't use rand() for security. If you need a cryptographically secure number"

Einfach open(/dev/urandom) und read(fd, &myint, 4) (so würde ich das machen)

Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von heinz » 04.01.2019 23:04:59

Hallo hikaru,

Wow, äääh...
Erstmal vielen Dank fuer Deine ausfuehrliche Erklaerung!
hikaru hat geschrieben: ↑ zum Beitrag ↑
04.01.2019 22:45:30
...dass in deiner Polarkoordinatentransformation der Term für die Winkelfunktionen ( winkel * (Pi / 180.0) ) überdurchschnittlich häufig Werte nahe Null und Eins annimmt.

...dafür sorgen, dass deine Punkte gleichmäßig auf dem Quadrat des Radius' verteilt sind.
Koenntest Du mir einen Tipp geben, wie ich das vermeide/umsetze oder eine Seite im Netz, wo es "leicht" verstaendlich erklaert wird?
Meine Mathe-Kenntnisse sind leider nur sehr rudimentaer... :oops:

Gruss heinz

Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von heinz » 04.01.2019 23:12:12

Hallo schorsch,
schorsch_76 hat geschrieben: ↑ zum Beitrag ↑
04.01.2019 23:00:49
Einfach open(/dev/urandom) und read(fd, &myint, 4) (so würde ich das machen)
Danke fuer die Anregung!
Werde es mal testen und mich wieder melden...

Gruss heinz

Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von heinz » 04.01.2019 23:40:09

Hallo nochmal,

also ich hab es jetzt mal mit "/dev/urandom" versucht und das Ergebnis war
leider die selbe "Kreuz-Verteilung".
Aber trotzdem wieder was gelernt. Habe bis jetzt immer in Programmen "rand()%int" verwendet.
Wie ich gesehen habe, nicht die beste Entscheidung...
Danke fuer den Tipp!

Ich werde mich mal auf die Suche nach den Tipps von hikaru machen.
Vlt. passt in mein altes Hirn ja noch was rein... :lol:

Melde mich wieder, wenns was neues gibt ...

Gruss heinz

Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von heinz » 04.01.2019 23:46:10

Hallo MSfree,

sorry, hab Deine Nachricht fast uebersehen...
MSfree hat geschrieben: ↑ zum Beitrag ↑
04.01.2019 22:43:10
Ich würde es mal folgendermassen Umsetzen:

Es gibt alternativ auch noch andere Zufallsfunktionen, die Direkt z.B. ein double zwischen 0.0 und 1.0 liefern, ...
Werde es ausprobieren und mich wieder melden...

Gruss heinz

Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von heinz » 05.01.2019 00:06:53

Hallo MSfree,

habe Deine Vorschlaege gerade mal getestet.
In beiden Faellen ( der Code-Vorschlag und drand48() ) leider keine veraenderung...

Gruss heinz

Benutzeravatar
hikaru
Moderator
Beiträge: 13900
Registriert: 09.04.2008 12:48:59

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von hikaru » 05.01.2019 00:08:49

hikaru hat geschrieben: ↑ zum Beitrag ↑
04.01.2019 22:45:30
...dass in deiner Polarkoordinatentransformation der Term für die Winkelfunktionen ( winkel * (Pi / 180.0) ) überdurchschnittlich häufig Werte nahe Null und Eins annimmt.
Korrektur:
Nicht der Wert in der Klammer nimmt Werte nahe* Null oder Eins an, sondern der ganze Sinus- bzw. Kosinus-Term. Der Teil in der Klammer sollte dementsprechend immer nahe einem Vielfachen von π/2 sein.
Das wiederum würde bedeuten, dass dein winkel häufig nahe einem Vielfachen von 90° ist, was ja auch im Bild zu sehen ist.
Allerdings glaube ich nicht, dass du so einen Effekt übersehen hättest, oder dass selbst der schlechteste Pseudozufallsgenerator solche Werte liefert. Da muss irgendwas bei den weiteren Umrechnungen schiefgehen (Rundungseffekte, Typecasting, Mondphase?).
heinz hat geschrieben: ↑ zum Beitrag ↑
04.01.2019 23:04:59
Koenntest Du mir einen Tipp geben, wie ich das vermeide/umsetze oder eine Seite im Netz, wo es "leicht" verstaendlich erklaert wird?
Das ist bezogen auf den Winkel leider genau der Teil den ich nicht erklären kann.
Vielleicht würde es helfen, wenn du die Zufallswinkel direkt in Radians erzeugst, statt in Grad (Wertebereich 0-2π, statt 0-360). Keine Ahnung ob das in c geht. MSfrees Ansatz klingt recht vielversprechend. Vielleicht gibt es eine Zufallsfunktion die Radians-Werte ohne Umrechnung liefern kann.

Was die Dichte angeht, mappe deine Zufallszahlen auf ihr jeweiliges Quadrat! Also 1 zu 1, 2 zu 4, 3 zu 9 usw.
Das dehnt natürlich deinen Radius auf 2000² aus. Falls du das nicht willst: 45² = 2025.

Edit:
Das war Quatsch! Du musst dafür sorgen, dass die Wahrscheinlichkeit p, dass ein Punkt einen Radius r hat proportional zu r² ist. Wenn also für r=1 gilt: p=1, dann musst du dafür sorgen, dass für r=2 gilt: p=4, für r=3: p=9 usw.
Einen brauchbaren Implementierungsvorschlag kriege ich aber um diese Uhrzeit nicht mehr auf die Reihe.

Gute Nacht!


*) aber nicht unbedingt gleich

Benutzeravatar
Lohengrin
Beiträge: 3227
Registriert: 29.08.2004 00:01:05
Wohnort: Montsalvat

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von Lohengrin » 05.01.2019 03:55:23

heinz hat geschrieben: ↑ zum Beitrag ↑
04.01.2019 21:54:18
Leider sind die Positionen nicht richtig gleichmaessig verteilt
Zuerst mal zu radius.
So wie du es gebaut hast, gibt das eine Gleichverteilung auf die 2000-Elementige Punktemenge {0.0, ..., 199.9}. In der Fläche betrachtet ist das nicht gleichmäßig, denn 187.6 kommt genauso häufig vor wie 3.4, aber der Ring mit Radius 187.6 plusminus 0.05 hat viel mehr Fläche als der Ring mit Radius 3.4 plusminus 0.05, und es landen gleich viele Punkte in den Ringen. Wenn du die Ringe auseinanderwickelst, hast du nahezu Rechtecke mit Kantelnänge 187.6*2*π und 0.1 und Kantenlänge 3.4*2*π und 0.1. (π habe ich mit mit Strg+Shift+u 3c0 Enter geschrieben, nachdem ich nachgeschaut habe, dass das das Unicodezeichen U+03C0 ist.) Du musst das passend strecken. Genau das machst du bei der Substitution im Integral, wenn du von kartesischen Koordinaten auf Polarkoordinaten wechselst, und dabei der Radius als Steckfaktor (Determinante der Ableitung der Transformation) auftaucht.

Mich erinnert das an "π mit Montecarlo berechnen" aus der Reihe "Viele Möglichkeiten, π zu bestimmen". Da schießt man n mal gleichverteilt mit x zwischen -1 und 1 und y zwischen -1 und 1, dann zählt man die Treffer, wo x^2+y^2 < 1 ist, sei das t. Dann ist, weil der Kreis Fläche π hat, und das Quadrat die Fläche 4, π=4*t/n.
So könntest du es auch machen: x und y gleichverteilt wählen, und wenn x^2+y^2 > 1 ist, wegschmeißen.

Nun zu winkel.
Ich habe mal herumgespielt, Folgendes gemacht.

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main ()
{
  int a=0;
  int b=0;
  int c=100000000;
  for (int z=0; z<c; z++)
    {
      float winkel= (float) (rand()% 36000000) / 100000.0;
      float s= sin(winkel * (M_PI / 180.0));
      if ( s == 0.0 ) printf("Eine Null!\n");
      if (s > 0.0 && s < 0.1) a++;
      if (s > 0.1 && s < 0.2) b++;
    }
  printf("%d: %d %d\n",c,a,b);
}
Ergebnis

Code: Alles auswählen

Eine Null!
Eine Null!
100000000: 3207015 3239142
Demnach ist der Sinus nicht ungewöhnlich häufig nahe bei 0. Das scheint mir ein Artefakt bei der grafischen Darstellung zu sein.

Wie hast du die Grafik gemacht?
Harry, hol schon mal das Rasiermesser!

rendegast
Beiträge: 15041
Registriert: 27.02.2006 16:50:33
Lizenz eigener Beiträge: MIT Lizenz

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von rendegast » 05.01.2019 07:27:20

hikaru hat geschrieben: Edit:
Das war Quatsch! Du musst dafür sorgen, dass die Wahrscheinlichkeit p, dass ein Punkt einen Radius r hat proportional zu r² ist. Wenn also für r=1 gilt: p=1, dann musst du dafür sorgen, dass für r=2 gilt: p=4, für r=3: p=9 usw.
Einen brauchbaren Implementierungsvorschlag kriege ich aber um diese Uhrzeit nicht mehr auf die Reihe.
Wurzel ( Zufall(0,1) ) * Kreisradius
?
mfg rendegast
-----------------------
Viel Eifer, viel Irrtum; weniger Eifer, weniger Irrtum; kein Eifer, kein Irrtum.
(Lin Yutang "Moment in Peking")

Benutzeravatar
detix
Beiträge: 1743
Registriert: 07.02.2007 18:51:28
Wohnort: MK

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von detix » 05.01.2019 11:05:12

Sehr gut erklärt wird es auch hier [1], das Stichwort „Montecarlo” ist ja schon gefallen.
Es ist für Excel geschrieben aber 1zu1 in LibreOffice Calc übernehmbar, daraus die Berechnungen für C abzuleiten sollte nicht allzu schwer sein...
[1] https://www.tabellenexperte.de/der-zufall-als-assistent
Gruß an alle Debianer, und immer daran denken:
Macht ohne Haftung funktioniert nicht!

reox
Beiträge: 2521
Registriert: 06.06.2006 22:09:47
Lizenz eigener Beiträge: MIT Lizenz

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von reox » 05.01.2019 11:41:07

Interessant, ich habs mal in python implementiert:

Code: Alles auswählen

import numpy as np
import matplotlib.pyplot as plt

N = 10000

r = 1

winkel = 2 * np.pi * np.random.rand(N)
radius = r * np.random.rand(N)
x = np.sin(winkel) * radius;
y = np.cos(winkel) * radius;

plt.scatter(x, y)
plt.show()
und komme auf das hier:
1994

Ich berechne mir den Winkel aber direkt in radians, da np.random.rand() mir eine uniforme verteilung zwischen [0, 1] liefert.
Vermutlich ist das mit dem Modulo einfach nicht so gut.
Das die punktwolke mit zunehmendem radius weniger dicht ist, erscheint mir logisch.


Hier noch eine andere Idee:
man erzeugt Koordinatenpaare (x, y) und testet ob diese innerhalb des Kreises liegen. Dadurch erzeugt man eine homogene Punktverteilung innerhalb der Ebene und nicht eine homogene Verteilung der Polarkoordinaten.
Hier mal für den ersten Quadraten - man müsste eben die Vorzeichen für x und y noch variieren...

Code: Alles auswählen

import random
import matplotlib.pyplot as plt

def points(N, r):
    c = 0
    while c < N:
        x = random.random()
        y = random.random()
        if x**2 + y**2 <= r**2:
            c += 1
            yield x, y

x, y = zip(*points(10000, 1))

plt.scatter(x, y)
plt.show()
1995
Zuletzt geändert von reox am 05.01.2019 11:56:32, insgesamt 2-mal geändert.

Benutzeravatar
rvb
Beiträge: 2
Registriert: 18.12.2018 12:20:57
Wohnort: Nowosibirsk
Kontaktdaten:

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von rvb » 05.01.2019 11:50:55

reox hat geschrieben: ↑ zum Beitrag ↑
05.01.2019 11:41:07
Vermutlich ist das mit dem Modulo einfach nicht so gut.
Ein einfaches Beispiel: angenommen, du hättest einen perfekten Zufallsgenerator, der Zahlen zwischen 0 und 8 absolut gleichverteilt liefert, aber möchtest eine Zufallszahl im Intervall [0,5] haben. Wenn du dazu einfach das Ergebnis des Zufallsgenerators modulo 6 nimmst, dann kriegst du zwar eine Zufallszahl im Intervall [0,5], aber die landet mit 2/3 Wahrscheinlichkeit im Intervall [0,2] und nur mit 1/3 Wahrscheinlichkeit im Intervall [3,5].

Das beste /dev/urandom hilft also nichts, wenn man hinterher ein Modulo dranhängt.
Zuletzt geändert von rvb am 05.01.2019 14:16:57, insgesamt 1-mal geändert.

Benutzeravatar
hikaru
Moderator
Beiträge: 13900
Registriert: 09.04.2008 12:48:59

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von hikaru » 05.01.2019 12:33:45

Lohengrin hat geschrieben: ↑ zum Beitrag ↑
05.01.2019 03:55:23
Demnach ist der Sinus nicht ungewöhnlich häufig nahe bei 0. Das scheint mir ein Artefakt bei der grafischen Darstellung zu sein.
Nachdm ich eine Nacht darüber geschlafen habe, denke ich, dass das doch ein Effekt der Sinus- bzw. Kosinusfunktion ist, bzw. heinz' Erzeugung der Werte für den Winkel in Grad als Integer.
Schauen wir uns mal das Diagramm zu den Funktionen an. [1] Der Radius den heinz mit 2000 definiert hat, wird hier auf der Hochachse auf ±1 normiert und die Werte sollten durch den Zufallsgenerator gleichmäßig in diesem Wertebereich verteilt sein.
Nun haben aber die Funktionen an ihren Nullstellen jeweils einen großen Anstieg, die gleichmäßig auf der Hochachse verteilten Punkte haben also einen kleinen horizontalen Abstand, während es nahe den Maxima genau andersrum ist. So erzeugt in heinz' Code die Sinusfunktion den "Balken" auf der y-Achse, während die Kosinusfunktion den "Balken" auf der x-Achse erzeugt.

Um ein halbwegs anschauliches Beispiel zu bringen, schauen wir uns mal 4 Punkte an, die alle auf dem Rarius r liegen:
A: φ=0°; B: φ=1°; C: φ=45°; D: φ=46°

Der Kosinus von A und B unterscheidet sich erst bei 10^-4, während C und D sich schon bei 10^-2 unterscheiden. Der Abstand zwischen A und B ist nahe 1, da sie kartesisch fast die selbe x-Koordinate haben. C und D unterscheiden sich dagegen in x unyd y um jeweils 1, was dazu führt, dass ihr Abstand nicht 1 sondern Wurzel 2 ist.
Was man tun müsste, wäre die Wahrscheinlichkeit eines Winkels nicht gleich zu verteilen, sondern an die Summe seines Sinus+Kosinus zu koppeln.

Oder man erzeugt gleich Radians wie reox' Beispiel zeigt.

rendegast hat geschrieben: ↑ zum Beitrag ↑
05.01.2019 07:27:20
Wurzel ( Zufall(0,1) ) * Kreisradius
?
Sieht gut aus!
In reox' Beispiel:

Code: Alles auswählen

radius = r * np.sqrt ( np.random.rand(N) )

[1] https://de.wikipedia.org/wiki/Datei:Sin ... period.svg

reox
Beiträge: 2521
Registriert: 06.06.2006 22:09:47
Lizenz eigener Beiträge: MIT Lizenz

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von reox » 05.01.2019 13:49:50

hikaru hat geschrieben: ↑ zum Beitrag ↑
05.01.2019 12:33:45
In reox' Beispiel:

Code: Alles auswählen

radius = r * np.sqrt ( np.random.rand(N) )
In der tat, das erzeugt eine bessere verteilung:
1996

Benutzeravatar
smutbert
Beiträge: 8342
Registriert: 24.07.2011 13:27:39
Wohnort: Graz

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von smutbert » 05.01.2019 13:53:02

Ich liebe das Debianforum für solche Threads!!

reox hat (leider :wink:) die Idee mit dem Verwerfen von Koordinaten, die außerhalb des Kreises liegen schon gepostet, sonst hätte ich auch etwas posten können (ich meine etwas anderes als nur die Feststellung, dass ich solche Thread gerne lese).

Benutzeravatar
MSfree
Beiträge: 11604
Registriert: 25.09.2007 19:59:30

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von MSfree » 05.01.2019 14:07:57

reox hat geschrieben: ↑ zum Beitrag ↑
05.01.2019 11:41:07
Interessant, ich habs mal in python implementiert:
und ich habe mal schnell C-Code zusammengeklöppelt: NoPaste-Eintrag40569

Dabei habe ich die von mir oben vorgeschlagenen MyRandom-Funktion verwendet, allerdings in "double" statt "float". Ich kann dabei keine Kreuzstruktur erkennen. Die Häufung um die Mitte ist ja schon erklärt worden, wer mag, kann das C-Programm ja noch entsprechend anpassen :wink:

1997

Benutzeravatar
hikaru
Moderator
Beiträge: 13900
Registriert: 09.04.2008 12:48:59

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von hikaru » 05.01.2019 14:19:16

smutbert hat geschrieben: ↑ zum Beitrag ↑
05.01.2019 13:53:02
die Idee mit dem Verwerfen von Koordinaten,
Die Idee ist algorithmisch gut, aber um ehrlich zu sein finde ich den Weg als Lösung der Aufgabe hässlich.
Das Ziel ist ja, Punkte in einem Kreis zu erzeugen. Übertragen wir das in die Praxis:
Ich stelle eine Zielscheibe auf, gebe dir ein Paintball-Gewehr und stelle die Aufgabe, Kleckse auf der Zielscheibe zu erzeugen.
Nehmen wir an, du bist ein mäßiger Schütze, der zwar nur zufällig genau die Mitte trifft, aber es immerhin hinkriegt, zuverlässig die Scheibe zu treffen. Der naheliegende Lösungsweg wäre für dich, auf die Scheibe zu zielen und das Magazin leerzuballern.
Die Alternative wäre, wild um dich zu schießen und hinterher den Raum zu putzen. Gefällt mir als Putzmuffel jetzt nicht so sehr. ;)
MSfree hat geschrieben: ↑ zum Beitrag ↑
05.01.2019 14:07:57
Dabei habe ich die von mir oben vorgeschlagenen MyRandom-Funktion verwendet, allerdings in "double" statt "float". Ich kann dabei keine Kreuzstruktur erkennen.
Nein, kannst du nicht, denn du erzeugst deine Winkelwerte direkt als Gleitommawerte (ob float oder double sollte egal sein). Wenn ich es richtig verstehe, hat heinz hat seine Winkelwerte ursprünglich als Integer erzeugt und erst im zweiten Schritt ein Typecasting gemacht. Dadurch hat er im Gegensatz zu dir eine Diskretisierung seiner Werte, die nahe der Achsen in Folge des Verlaufs der trigonometrischen Funktionen als Balken zu sehen ist.

reox
Beiträge: 2521
Registriert: 06.06.2006 22:09:47
Lizenz eigener Beiträge: MIT Lizenz

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von reox » 05.01.2019 14:26:31

hikaru hat geschrieben: ↑ zum Beitrag ↑
05.01.2019 14:19:16
smutbert hat geschrieben: ↑ zum Beitrag ↑
05.01.2019 13:53:02
die Idee mit dem Verwerfen von Koordinaten,
Die Idee ist algorithmisch gut, aber um ehrlich zu sein finde ich den Weg als Lösung der Aufgabe hässlich.
Ja, vor allem verbrät man unnötig Zeit mit dem Aussortieren. Andererseits, wie kann man einen (oder zwei) Werte generieren, welche gleich die Kreisbedingung erfüllen? Die Euklidischen Koordinate sind immer abhängig voneinander, die Polarkoordinaten nicht - eine Lösung mit Polarkoordinaten haben wir, insbesondere das mit der Wurzel gefällt mir sehr gut!
Was mir nur einfallen würde, aber eher auch wenig Sinn macht, wäre sowas wie eine Hilbert Kurve für Kreise zu haben, damit man jedem Punkt eine Zahl zuordnen kann. Dann brauche ich nur eine Zufallszahl generieren und kann mir daraus die Position innerhalb des Kreises errechnen.

Benutzeravatar
MSfree
Beiträge: 11604
Registriert: 25.09.2007 19:59:30

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von MSfree » 05.01.2019 14:34:18

hikaru hat geschrieben: ↑ zum Beitrag ↑
05.01.2019 14:19:16
Nein, kannst du nicht, denn du erzeugst deine Winkelwerte direkt als Gleitommawerte (ob float oder double sollte egal sein).
Jein, denn rand() liefert immer ein int, das ich allerdings sofort in ein double umwandele.
Wenn ich es richtig verstehe, hat heinz hat seine Winkelwerte ursprünglich als Integer erzeugt und erst im zweiten Schritt ein Typecasting gemacht.
Wenn man die ursprüngliche Methode

Code: Alles auswählen

float winkel= (float) (rand()% 36000000) / 100000.0;
so steckt da zunächst

Code: Alles auswählen

rand()% 36000000
also der 100000-fache Winkelwert als int drin, der dann durch Division ein float ergibt. Das erklärt also die Häufung um die x- und y-Axen nicht.

Ich habe jetzt noch meinen Punktgenerator so implementiert, wie es Heinz ursprünglich hatte, also mit Modulus, aber mit double:

Code: Alles auswählen

void GeneratePoints( int numPts, double *x, double *y )
{
  int i;
  int method = 1;

  switch( method )
  {
    case( 0 ):
      for( i=0 ; i<numPts ; i++)
      {
        double winkel= MyRandom( 360.0 );
        double radius= MyRandom( 200.0 );
        x[i] = sin( winkel * (M_PI / 180.0) ) * radius;
        y[i] = cos( winkel * (M_PI / 180.0) ) * radius;
      }
      break;
    case( 1 ):
      for( i=0 ; i<numPts ; i++)
      {
        double winkel= (double) (rand()% 36000000) / 100000.0;
        double radius= (rand()% 2000) / 10.0;
        x[i] = sin( winkel * (M_PI / 180.0) ) * radius;
        y[i] = cos( winkel * (M_PI / 180.0) ) * radius;
      }
      break;
  }
}
Und, was soll ich sagen? Das ergebnis zeigt ebenfalls keine Häufung an den Achsen:
1998

Benutzeravatar
king-crash
Beiträge: 739
Registriert: 08.08.2006 12:07:56
Lizenz eigener Beiträge: MIT Lizenz

Re: Probleme beim Zufalls-Punkte erzeugen

Beitrag von king-crash » 05.01.2019 14:47:53

Das Problem ist der Modulo.
Ein einfaches Beispiel:
Eine 2 Bit Zahl, komplett zufällig, kann also folgende Werte annehmen:
00
01
10
11
Machst du jetzt Beispielsweise Moduo 3:
00 -> 00
01 -> 01
10 -> 10
11 -> 00
Somit kommt 0 mit der doppelten Wahrschinlichkeit vor.

Antworten