random float



  • Für Fließkommazahlen wären trickreiche Umwandlungen nötig. Wenn Du da jetzt nicht gerade einen riesenspaß dran hast würde ich einfach was fertiges nehmen. Sehr gut finde ich persönlich das entsprechende Modul aus der boost-Bibliothek. Hier ein eigens für Dich umgestricktes Beispiel:

    #include <iostream>
    #include <boost/random.hpp>
    
    int main()
    {
        // Zufallsgenerator
        boost::mt19937 generator(42u);
    
        // Gewünschte Verteilung. Hier Gleichverteilung.
        boost::uniform_real<> uni_dist(0,30);
    
        // Dieses Ding setzt nun den "Zufall" in die gewünschte Verteilung um:
        boost::variate_generator<boost::mt19937&, boost::uniform_real<> > uni(generator, uni_dist);
    
        // Jetzt kannst Du Zufallszahlen erzeugen
        for(int i = 0; i < 10; ++i)
            std::cout << uni() << std::endl;
    
        return 0;
    }
    


  • Ah, tschuldigung. Das ist ja das ANSI-C Forum. Pardon. Ich lass' es trotzdem mal stehen, weil es vielleicht jemand anders über die Suchfunktion findet und gebrauchen kann.

    Für C gibt es Zufallsgeneratoren in der Gnu Scientific Library. Das ist eine sehr empfehlenswerte Bibliothek, die sich bei meiner Diplomarbeit ziemlich bewährt hat.
    Hier der Link:
    http://www.gnu.org/software/gsl/



  • Hallo,

    Ich nutze windows und weiß leider nicht wie in diese gsl bib installiere. (reicht es alle dateien/ordner in den include ordner zu kopieren?)
    sollte die installation zu kompliziert sein:
    vl. kann jemand eine .txt mit 100.000 floats (gesamter Wertebereich) hochladen.

    mfg Christoph



  • Ermittel Dir mit rand() einfach zwei Integer-Werte, dividiere sie durcheinander, und Du hast einen float - Wert.



  • 4 Byte-Zahl ( Vorzeichen, Mantisse ) und Exponenten getrennt erzeugen,
    dann den Exponenten ( -125...128 ) in die Zahl einfügen, könnte es so gehen?



  • Naja, so schlecht war die Ursprungsidee gar nicht, Vor- und Nachkommateil getrennt zu erzeugen:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    float GiveMeFloat()
    {
    	float f, tmp;
    
    	f = rand();
    	tmp = rand();
    	f = f + tmp / log10(tmp);
    
    	return f;
    }
    
    int main()
    {
    	int i;
    
    	srand (time(NULL));
    
    	for(i = 0; i < 10; ++i)	
    	{
    		printf("Mein Zufallsfloat ist %f\n", GiveMeFloat());
    	}
    }
    


  • @belli

    danke für die hilfe, aber leider ist das hauptproblem noch immer nicht gelöst:
    die floats sollen auch wirklich den gesamten wertebereich
    (1.2E-38 bis 3.4E+38) bzw. FLT_MIN bis FLT_MAX aus <float.h> abdecken.
    außerdem sollten die zufallszahlen über den bereich gleichmäßig verteilt sein.

    mfg Christoph



  • Wenn Dir egal ist, wie die Zahlen entstehen (Du schriebst ja, dir soll jemand fertige Zahlen hochladen), dann nimm doch meinen C++-Code von oben, ersetze die Grenzen durch FLT_MIN und FLT_MAX, jage das ganze durch den Compiler und fertig.

    Oder nimm eine Skriptsprache wo das ganze schon eingebaut ist. Z.B. Python.

    Wenn Du trotzdem eine gute Lösung in C habe willst und unbedingt alles von FLT_MIN bis FLT_MAX abgedeckt haben willst, dann musst Du Dir die Arbeit machen und dich um eine Bibliothek bemühen.



  • Okay, eine Idee hätte ich noch:
    Mach eine UNION aus einem float und einem int -- die belegen beide 32 Bit. Nun ermittel 32 Zufallszahlen zwischen 0 und 1 und weise sie den einzelnen Bits zu. So sollten eigentlich alle möglichen floats erzeugt werden können.



  • Hallo,

    Danke für die gute Idee.
    Leider bin ich in C noch nicht wirklich gut.
    Ich kann zwar die einzelnen "bits" (zufalls01) erzeugen, weiß aber nicht wie ich die beschriebene "union" codiere. kannst du mir ein beispiel geben?!

    mfg Christoph



  • Damit läufst du gefahr, ungültige floats zu erzeugen, weil der Exponent nicht kleiner als -125 sein darf. Daher meine Idee, den Exponenten getrennt zu erzeugen.



  • Also, ich habe mir das in etwa so vorgestellt:

    // Erzeugt eine zufällige 32 Bit Integer Zahl
    unsigned random_integer32bit ()
    {
    	unsigned num = 0;
    	int i;
    
    	for ( i=0; i<32; i++ )
    	{
    		num <<= 1;
    	 	if ( rand() % 2 ) 
    			num |= 1;
    	}
    	return num;
    }
    
    // Liefert einen zufälligen Exponenten von FLT_MIN_EXP bis FLT_MAX_EXP 
    // FLT_MIN_EXP -125
    // FLT_MAX_EXP 128 
    signed char random_exponent () 
    {
    	float r = FLT_MAX_EXP - FLT_MIN_EXP; 
    	return (signed char) ( FLT_MIN_EXP + (int)(r * rand()/(RAND_MAX))) ; 
    }
    
    int main ( )
    {
    	int i;
    	unsigned num, exp;
    	float fnum = -FLT_MAX;
    
    	//memcpy(&num, &fnum, 4);
    	//bin_view(num);
    	srand( (unsigned)time(NULL) );
    
    	// 4 Byte Zufallszahl erzeugen.
    	num = random_integer32bit ();
    	// Zufallszahl könnte NaN sein, wenn Exponent < -125
    	// Exponenten 0 setzen, UND-verknüpfen mit der Zahl
    	// 0x807FFFFF hex =  10000000011111111111111111111111 bin
    	num &= 0x807FFFFF;
    
    	// Zufälligen Exponenten im Bereich -125 ... 128 erzeugen.	
    	exp = random_exponent ();
    
    	// Exponent ist in der Form
    	// 000000000000000000000000xxxxxxxx
    	// Exponenten um 23 Bit nach links verschieben
    	exp <<= 23;
    	// Jetzt sollte der Exponent an der richtigen Position sein
    	// 0xxxxxxxx00000000000000000000000
    
    	// Überflüssige FFs entfernen
    	exp &= 0x7F800000;
    	//	0x7F800000 hex =  01111111100000000000000000000000 bin
    
    	// Exponenten in die Zahl per ODER-Verknüpfung einfügen.
    	num = num|exp;
    	// Die float-Version ist fertig.
    	memcpy( &fnum, &num, sizeof(float));
    
    	printf("%f\n", fnum );
    
    	return 0;
    }
    

    Das Dingen erzeugt auch negative Werte. Wenn du nur positive willst, setze das MSB auf 0.
    Auf manchen Maschinen ist RAND_MAX laut http://mail.gnome.org/archives/gtk-devel-list/2000-February/msg00219.html 2^32-1 groß.
    In dem Fall vereinfacht sich die Funktion random_integer32bit auf einen rand() Aufruf.



  • Hallo,

    Ich hab jetzt einfach mittels bitshift 32bit in einem integer zufällig gesetzt.
    jetzt möchte ich die adresse des int auf einem float zuweisen.
    Leider funktioniert das nicht so wie ich mir das vorstelle:

    int main()
    {
    	srand(time(NULL));
    	char bit;
    	int x,i;
    	float*f;
    
    	for(bit=0,x=0,i=0;i<32;i++)
    	{
    	bit=rand()%2;
    	x|=bit<<i;
    	}
    	f=&x; //Hier möchte ich, dass f die selbe Adresse wie x erhält
    	return 0;
    }
    


  • Mhm, ja, das ist ja so ähnlich, wie ich es mit der UNION vorgeschlagen hatte ...
    Was genau funktioniert denn nicht?
    Wenn Du ungültige Werte bekommst, kann das evtl. daran liegen, daß es Bitmuster gibt, die kein gültiges float sind, wie mathematikpraktikant sagte ...
    Mir war das gar nicht klar; ich war davon ausgegangen, daß alle Bitmuster erlaubt sind, und jeweils einen float - Wert repräsentieren.



  • Ich habs jetzt auch mal so probiert, das Ergebnis sieht erst mal ganz gut aus:

    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    union convert
    {
    	int i;
    	float f;
    };
    
    int main()
    {
    	int i;
    	union convert c;
    	srand(time(0));
    
    	for(i = 0; i < 10; ++i)
    	{
    		c.i = rand();
    		c.i = c.i << 16;
    		c.i = c.i + rand();
    		printf("Int = %d Float = %e\n", c.i, c.f);
    	}
    }
    

    Ein Problem ist, daß der größte von rand() erzeugte Wert (32767) auf meinem System immer eine 0 im MSB hat. Dieses Bit müsste man also jeweils noch einmal gesondert ermitteln/setzen.
    Ein anderes Problem ist wie erwähnt, daß ich nicht weiß, ob es auch ungültige Bitmuster gibt, die dann keinen gültigen float-Wert repräsentieren.



  • Hier wären nun alle Bits drin, wenn ich mich nicht irre:

    for(i = 0; i < 10; ++i)
    	{
    		c.i = rand();
    		c.i = c.i << 17;
    		c.i = c.i | (rand() << 1);
    		c.i = c.i | (rand() % 2);
    		printf("Int = %d Float = %e\n", c.i, c.f);
    	}
    


  • Belli schrieb:

    Ein anderes Problem ist wie erwähnt, daß ich nicht weiß, ob es auch ungültige Bitmuster gibt, die dann keinen gültigen float-Wert repräsentieren.

    Ein NaN ( not a number ) ist keine Zahl. Die Bitmuster von NaN stecken in den 4 Byte des float-Typen mit drin.



  • Ja, schon klar, aber wo? Soweit ich bisher durch Ausprobieren (und Wikipedia-Lesen) festgestellt habe, ist ein Wert untauglich, wenn der Exponent 255 ist. Wenn das tatsächlich die einzige untaugliche Kombination sein sollte, könnte man bei Auftreten zufällig eines der 8 Bits (des Exponenten) wieder löschen und hätte dann wieder einen float ...



  • Hallo,

    Bei deinem Code erhalte ich das gleiche Ergebnis wie bei meinem:
    Es werden zwar (haupsächlich) gültige floats ausgegeben.
    Leider stimmt aber die verteilung nicht.
    man müsste die bits im exponententeil so setzen. Dass die exponenten im verhältnis 10:1 zum vorigen auftreten:
    e038 soll 10 mal häufiger auftreten als e037 und 100mal öfter als e036

    mein ansatz wäre dafür:

    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    #include <math.h>
    
    int main()
    {
    	srand(time(NULL));
    	char bit,bitr;
    	int x,i,j,k,l;
    	float*f;
    
    	for(x=0,i=0;i<5;i++)
    	{
    		bit=rand()%2;
    		x|=bit<<31;
    		for(bit=0,j=0,k=7;j<8;j++,k--)
    		{
    			for(bit=0,l=0;l<pow(2,k);l++) 
    //rand() muss 2^k mal 0 sein damit das bit auch 0 gesetzt wir
    			{
    				bitr=rand()%2;
    				if(bitr==1)
    					bit=1;
    			}
    				x|=bit<<(j+22);
    		}
    		for(j=0;j<23;j++)
    				{
    					bit=rand()%2;
    					x|=bit<<j;
    				}
    		f=&x;
    		printf("%f\n",*f);
    	}
    	return 0;
    }
    

    ich hab also nur die bits logarithmiert (bit8 wird 2^8 mal öfter gesetzt als bit1)
    das müsste man jetzt aber eben so umformen, dass es nicht für die einzelnen bits, sondern für die codierten dezimalzahlen gilt.

    Ich hoffe das war nicht zu verwirrend.

    mfg Christoph



  • Belli schrieb:

    Ja, schon klar, aber wo? Soweit ich bisher durch Ausprobieren (und Wikipedia-Lesen) festgestellt habe, ist ein Wert untauglich, wenn der Exponent 255 ist. Wenn das tatsächlich die einzige untaugliche Kombination sein sollte, könnte man bei Auftreten zufällig eines der 8 Bits (des Exponenten) wieder löschen und hätte dann wieder einen float ...

    Also hier weiter unten
    http://de.wikipedia.org/wiki/NaN
    steht, das es 223 NaNs gibt 😮


Anmelden zum Antworten