random float



  • Hallo,

    ich würde gerne mit rand() eine zufällige float erzeugen:

    float rfv=(rand()<<16)+rand();
    		float rfn=rand()/(float)RAND_MAX;
    		float rf=rfv+rfn;
    

    rfv enthält hier die "vorkommateil" (zb. 123.0000000)
    rfn die "nachkommateil" (0.123456)
    jetzt will ich daraus durch addieren eine komplette float basteln (123.123456)
    leider funktioniert rf=rfv+rfn nicht (rf wird immer rfv)

    mfg christoph



  • erstelle lieber 1 oder 2 int variablen mit rand() und addiere sie, dann teilst du diese zahl durch 10 oder 100 oder 1000... je nachdem wo dein komma sein soll, das ergebnis weist du einer float variablen zu



  • Hallo,

    Leider konnte ich nach langer suche bei google noch immer keine Lösung finden.
    Daher habe ich es aufgegeben, selbst ein programm für rand floats zu schreiben.
    Leider benötige ich für eine weitere Aufgabe eine Liste mit min 10.000 floats.
    Kennt also jemand ein Programm das mir diese (im gesamten Wertebereich) erstellt.
    Bzw. eine fertige Liste mit den Werten?

    mfg Christoph



  • Warum willst du denn die Zahl unbedingt in Vor- und Nachkommaanteil zerlegen?
    Lass sie doch ganz.



  • Hallo,

    Das aus dem ersten Beitrag war nur ein versuch, da mir keine andere möglichkeit eingefallen ist. Solltest du wissen wie es geht, bin ich gerne bereit mir deine idee "anzuhören".

    mfg Christoph



  • 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.


Log in to reply