# Zufallsvariable zwischen 1.0 und 8.0



## Guest (12. Jan 2009)

Hallo,
wie kann ich am besten eine Zufallsvariable im Intervall [1.0,8.0] erzeugen.


----------



## ARadauer (12. Jan 2009)

fragt mich nicht ob das sinnvoll ist


```
Random rnd = new Random();
      System.out.println((rnd.nextFloat()*10)%8);
```


----------



## SlaterB (12. Jan 2009)

da haben aber Zahlen zwischen 0 und 2 eine doppelt so Chance wie die anderen,
alle Zahlen über 8.0 müssen verworfen werden, dann per Schleife eine neue Zufallszahl erstellen

weniger 'Verlust' gibts bei random.nextDouble() * 8.0001, 
bisschen Verlust aber immer noch und evtl. Probleme durch die Berechnung

edit:
das +1 fehlt auch noch, also alles über 7 weg und dann +1


----------



## Marco13 (12. Jan 2009)

???:L 
Eigentlich ganz einfach: 
float f = rnd.nextFloat()*8.0f;

Soll die 8.0 auch vorkommen können? Aufgrund der präzise erscheindenden Beschreibung
[1.0,8.0] 
vs.
[1.0,8.0)
gehe ich davon aus, dass die 8 auch dabei sein soll...Dann wird's ein bißchen komplizierter... sag' ggf. bescheid.


----------



## ARadauer (12. Jan 2009)

stimmt ;-)


```
package main.java;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Random;
import java.util.Set;

public class Test {


   public static void main(String[] args) {
      
      HashMap<Integer, Integer> counts = new HashMap<Integer, Integer>();
      
      Random rnd = new Random();
      for(int i = 0; i< 1000000; i++){
         float value = (rnd.nextFloat()*10)%8;
         Integer count  =counts.get((int) value);
         counts.put((int) value, count==null?1:count+1);  
         
      }
      
      Set<Integer> keys = counts.keySet();
      ArrayList<Integer> keyList = new ArrayList<Integer>(keys);
      Collections.sort(keyList);
      for(Integer key: keyList)
         System.out.println(key+": "+counts.get(key));
      
      
      System.out.println("besser");
      
     counts = new HashMap<Integer, Integer>();
      
      rnd = new Random();
      for(int i = 0; i< 1000000; i++){
         float value = rnd.nextFloat()*8f;
         Integer count  =counts.get((int) value);
         counts.put((int) value, count==null?1:count+1);  
         
      }
      
      keys = counts.keySet();
      keyList = new ArrayList<Integer>(keys);
      Collections.sort(keyList);
      for(Integer key: keyList)
         System.out.println(key+": "+counts.get(key));
     
      
      
   }
}
```


----------



## Guest (12. Jan 2009)

ja 8.0 soll auch dabei sein / sowie auch die 1.0


----------



## SlaterB (12. Jan 2009)

random.nextDouble() * 7.0001, 
prüfen ob <=7, sonst nochmal (auch mehrmals, Schleife!),

später +1


----------



## Guest (12. Jan 2009)

DANKE EUCH ALLEN FÜR DIE SCHNELLE UND KOMPETENTE HILFE!!!!!!


----------



## Milo (12. Jan 2009)

Hi,

vll noch ein Link zur Bestimmung von Gleichverteilte Zufallszahlen mit JavaScript.

Gruß Micha


----------



## Marco13 (12. Jan 2009)

Wer haätte gedacht, dass man auf diesen Beitrag auch mal aufgrund einer _Antwort_ verlinken muss: http://www.java-forum.org/de/topic17227_ihr-seid-falschen-forum.html :bae:

Das mit dem 7.0001 sieht ... merkwürdig aus. Ich würde eher sowas versuchen wie

```
int i = random.nextInt();
double d = i / (double)(Integer.MAX_VALUE-1);
float f = (float)(d*8);
```
... ???:L müßte eigentlich passen.


----------



## SlaterB (12. Jan 2009)

interessanter Gedankte, aber was hast du gegen Integer.MAX_VALUE? 
und auch negative Zahlen muss man bedenken

im Bereich nahe 0 sind die Sprünge recht sichtbar 'groß', weiter oben wird gerundet,
so führt nur int 0 zu double 0, aber 66 ints zu 8.0,

ist bei der normalen double-Rechnung wohl auch nicht viel anders und sicher nicht so wichtig


```
public class Test {

	public static void main(String[] args) {
		x(Integer.MAX_VALUE);
		x(Integer.MAX_VALUE - 1);
		x(Integer.MAX_VALUE - 2);
		x(Integer.MAX_VALUE - 3);
		x(Integer.MAX_VALUE - 30);
		x(Integer.MAX_VALUE - 60);
		x(Integer.MAX_VALUE - 63);
		x(Integer.MAX_VALUE - 65);
		x(Integer.MAX_VALUE - 66);
		x(Integer.MAX_VALUE - 67);
		x(Integer.MAX_VALUE - 75);
		x(Integer.MAX_VALUE - 90);
		x(Integer.MAX_VALUE - 100);
		x(Integer.MAX_VALUE - 300);
		x(Integer.MAX_VALUE - 3000);
		x(Integer.MAX_VALUE - 3001);
		x(Integer.MAX_VALUE - 3002);
		x(Integer.MAX_VALUE - 3003);
		x(Integer.MAX_VALUE - 3004);
		x(Integer.MAX_VALUE - 3005);
		x(Integer.MAX_VALUE - 3006);
		x(Integer.MAX_VALUE - 3007);
		x(Integer.MAX_VALUE - 3008);
		x(Integer.MAX_VALUE - 3009);
		x(Integer.MAX_VALUE - 3010);
		x(Integer.MAX_VALUE - 3011);
		x(Integer.MAX_VALUE - 3021);

		x(1000003);
		x(1000002);
		x(1000001);
		x(100001);
		x(10001);
		x(1000);
		x(100);
		x(10);
		x(1);
		x(0);
	}

	static void x(int i) {
		double d = i / (double) (Integer.MAX_VALUE - 1);
		float f = (float) (d * 8);
		System.out.println(f + " -- " + i + " -- " + (Integer.MAX_VALUE - i));
	}

}

-------

8.0 -- 2147483647 -- 0
8.0 -- 2147483646 -- 1
8.0 -- 2147483645 -- 2
8.0 -- 2147483644 -- 3
8.0 -- 2147483617 -- 30
8.0 -- 2147483587 -- 60
8.0 -- 2147483584 -- 63
8.0 -- 2147483582 -- 65
7.9999995 -- 2147483581 -- 66
7.9999995 -- 2147483580 -- 67
7.9999995 -- 2147483572 -- 75
7.9999995 -- 2147483557 -- 90
7.9999995 -- 2147483547 -- 100
7.999999 -- 2147483347 -- 300
7.999989 -- 2147480647 -- 3000
7.999989 -- 2147480646 -- 3001
7.999989 -- 2147480645 -- 3002
7.999989 -- 2147480644 -- 3003
7.999989 -- 2147480643 -- 3004
7.999989 -- 2147480642 -- 3005
7.999989 -- 2147480641 -- 3006
7.999989 -- 2147480640 -- 3007
7.999989 -- 2147480639 -- 3008
7.9999886 -- 2147480638 -- 3009
7.9999886 -- 2147480637 -- 3010
7.9999886 -- 2147480636 -- 3011
7.9999886 -- 2147480626 -- 3021
0.0037253015 -- 1000003 -- 2146483644
0.0037252977 -- 1000002 -- 2146483645
0.003725294 -- 1000001 -- 2146483646
3.7253276E-4 -- 100001 -- 2147383646
3.725663E-5 -- 10001 -- 2147473646
3.7252903E-6 -- 1000 -- 2147482647
3.7252903E-7 -- 100 -- 2147483547
3.7252903E-8 -- 10 -- 2147483637
3.7252903E-9 -- 1 -- 2147483646
0.0 -- 0 -- 2147483647
```


----------



## Marco13 (12. Jan 2009)

SlaterB hat gesagt.:
			
		

> interessanter Gedankte, aber was hast du gegen Integer.MAX_VALUE?
> und auch negative Zahlen muss man bedenken



???:L Falls sich das darauf bezieht warum ich nicht durch Integer.MAX_VALUE sondern durch Integer.MAX_VALUE - 1 geteilt habe: Damit auch mal irgenwo 1.0 rauskommt (random.nextInt(100) liefert maximal 99 - damit man 1.0 bekommt muss man durch 99 teilen). Die negativen Zahlen hatte ich vergessen. Nicht so wichtig.

Das Runden ist natürlich ein Problem. (Die Bedenken, die ich diesbezüglich hatte, haben mich dazu bewogen, double zu verwenden - was das Problem aber vermutlich nicht komplett löst...). Hab grad' nochmal in die Doku von Random.nextFloat() geschaut: Die macht das ziemlich ähnlich wie das, was ich beschrieben hatte, aber dort sind auch Rundungsprobleme erwähnt. Wenn mich nicht alles täuscht, müßte es dann aber mit
random.nextInt(1<<24) / (float)((1<<24) - 1);
hinhauen? Aber ich denke, mit sowas wie
float f = (float) ((random.nextInt(N) / (double) (N - 1)) * 8);
für ein "großes" N, vielleicht 100000 oder so, ist man in jedem Fall schon gut dabei...


----------



## Guest (12. Jan 2009)

Hallo Slater



			
				SlaterB hat gesagt.:
			
		

> da haben aber Zahlen zwischen 0 und 2 eine doppelt so Chance wie die anderen,
> alle Zahlen über 8.0 müssen verworfen werden, dann per Schleife eine neue Zufallszahl erstellen
> 
> weniger 'Verlust' gibts bei random.nextDouble() * 8.0001,
> ...



Wie kommt das das die Zahlen zwischen 0 und 2 eine doppelt so hohe Chance haben wie die anderen?


----------



## Marco13 (12. Jan 2009)

int x = rnd.nextFloat()*10;
liefert (stark vereinfacht gesagt) alle Zahlen zwischen 0 und 9 gleich oft. Wenn man das also 1000 mal aufruft, dann hat  man _ungefähr(!!!)_ 
100 mal die 0 
100 mal die 1
100 mal die 2
... 
100 mal die 9.

Allerdings werden durch das "...%8" die Zahlen 8 und 9 abgebildet auf die 0 und die 1, weil
...
6%8 = 6,
7%8 = 7, aber
8%8 = 0 und 
9%8 = 1.
Wenn man das also 1000 mal aufruft, dann hat man _ungefähr(!!!)_ 
*200* mal die 0
*200* mal die 1, aber nur  
*100* mal die 2
... 
*100* mal die 7 
(und nie die 8 und die 9, weil die durch das %8 ja zur 0 bzw. 1 werden)


----------



## SlaterB (12. Jan 2009)

Marco13 hat gesagt.:
			
		

> random.nextInt(100) liefert maximal 99 - damit man 1.0 bekommt muss man durch 99 teilen


und random.nextInt(MAX) würde sicherlich 0 bis MAX-1 geben, aber das muss ja nicht für nextInt() selber auch gelten 

habs grad nicht ausprobiert, kann sicher auch dauern, 
die Javadoc klang aber danach


----------



## 0x7F800000 (13. Jan 2009)

leuts, kP was ihr hier macht, aber vielleicht würde das:

```
rand=randomizer.nextFloat()*Math.nextUp(up-down)+down;
```
hier jemanden weiterbringen? es sollen doch zahlen aus [1,8] geliefert werden, hab ich das richtig verstanden?

Hier ein test der methode:

```
import java.util.*;

public class TEST {
public static void main(String... _){
	float up=8f, down=1f;
	float rand;
	boolean upFlag=false, downFlag=false;
	
	Random randomizer=new Random(1234567);
	for(int i=0; i<1000000000; i++){
		rand=randomizer.nextFloat()*Math.nextUp(up-down)+down;
		upFlag|=(rand==up);
		downFlag|=(rand==down);
		if(rand>up){
			System.out.println(">up"); break;
		}
		if(rand<down){
			System.out.println("<down"); break;
		}
	}
	System.out.println("up: "+upFlag+" down: "+downFlag);
}
}
```
es produziert auf diese art und weise paar milliarden mal eine zufallszahl (die imho uniform verteilt sein muss)
Dann wird jedes mal geprüft, ob die zahl wirklich aus dem intervall kommt [ansonsten fliegt man aus der schleife] und zusätzlich wird geprüft, ob minimum und maximum angenommen werden [wird am ende ausgegeben, beides mal "true" sollte da rauskommen]


----------



## SlaterB (13. Jan 2009)

hast du das getestest?
bei mir kommt nur false für up, wie sollte da auch 8.0 erreicht werden,
höchstens durch Runden

ich benutzte allerdings auch nur ein schlichtes (up-down) manges Java 1.6


----------



## 0x7F800000 (13. Jan 2009)

Du hast also Math.nextUp() weggelassen, und wunderst dich, dass da keine 8.0 rauskommt? 
Ist nextFloat() eigentlich rechner & bs-unabhängig? Habe das seed für den Random eigentlich schon so ausgesucht, dass da auch nach wesentlich wenigeren versuchen die extrema angenommen werden.


----------



## SlaterB (13. Jan 2009)

ich habe die API gelesen und kann auch 7 direkt einsetzen und es ändert sich nix, 
daher ja die Frage, ob da jemals was passieren sollte?

nur wenn Math.nextUp(up-down) 7.0001 (oder gar 8? was spricht gegen +1??) zurückgibt kann da was passieren,
aber da ist dann  nix neues?


----------



## 0x7F800000 (13. Jan 2009)

so, moment, ich raff überhaupt nicht was dein Problem grad ist? ???:L

```
System.out.println(7d+" != "+Math.nextUp(7d));
```
Ausgabe:

```
7.0 != 7.000000000000001
```
wenn ich dann zahlen von 1.0 inklusive bis 8.00000000000000001 exklusive erzeuge, und unter der 8.000000000000001 nichts außer der 8.0 ist, dann krieg ich doch grad 1.0 inklusive bis 8.0 inklusive.

Also, bei mir liefert der test zumindest das was es sollte :bahnhof:


----------



## SlaterB (13. Jan 2009)

also genau so wie es im zweiten Antwortpost auf Seite 1 schon steht, 
ich wußte ja nur nicht, was du mit der unbekannten Java6-Methode genau meinst,
diese echte Grenze ist natürlich schicker


----------



## 0x7F800000 (13. Jan 2009)

was heißt "schicker" es geht hier doch nicht drum ob's schick ist oder nicht, sondern darum dass es funzt oder nicht funzt


----------



## SlaterB (13. Jan 2009)

funzt


----------



## 0x7F800000 (13. Jan 2009)

ist doch eine übliche slang-abkürzung für "*fun*k*t*ionier*t*" oder hab ich was verwechselt?^^ deutsch sprache schwer sprache


----------



## SlaterB (13. Jan 2009)

stimme zu, funktioniert


----------



## 0x7F800000 (13. Jan 2009)

dann versteh ich gar was du konkret mit dem letzten beitrag sagen wolltest, egal^^


----------



## Ebenius (13. Jan 2009)

Slater hatte einfach Math.nextUp() nicht gekannt und -- nachdem er sie durch die Konstante ersetzt hatte -- nicht mehr verstanden, wo die Innovation bei Deinem Post war.

Jetzt da er die Methode kennt, weiß er, was Du damit meinst und stimmt zu, dass es funktioniert und besserer Code ist als die Konstante 7.000000000000001 in den Code zu schreiben.



Ebenius


----------



## 0x7F800000 (13. Jan 2009)

aaah, sehet da: da spricht einer sogar in ganzen Sätzen  vorbildlich^^


----------



## Ebenius (13. Jan 2009)

Ich habe heimlich geübt. Aber nicht weiter sagen!


----------

