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 den "vorkommateil" (zb. 123.0000000)
    rfn den "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



  • probier mal den cast umzusetzen:

    float rfn=(float)rand()/RAND_MAX;
    

    🙂



  • Hallo,

    Danke für den Versuch, aber das ergebnis bleibt das gleiche.
    Das komische ist ja, dass rfv und rfn die korrekten werte enthalten und der Fehler erst bei der Addition auftritt.

    mfg Christoph



  • Siehst du denn die komplette Zahl? oder nur mit der e^irgendwas formatierung?
    Die kommazahl ist im vgl zu der Vorkommazahl verschwindend gering.
    Lass mal die Linksverschiebung weg dann siehst du es bei einer kleineren Zahl
    Vlt pfuscht dir da auch die autoformatierung bzw Rundung ins Handwerk 😉



  • Ich hab das jetzt überprüft und es wird tatsächlich immer aufgerundet (aus 126.0+0.01 wird 127.0)

    wie kann ich das umgehen?

    mfg Christoph



  • symbian schrieb:

    Ich hab das jetzt überprüft und es wird tatsächlich immer aufgerundet (aus 126.0+0.01 wird 127.0)

    wie kann ich das umgehen?

    mfg Christoph

    nenene

    double v = 126.0;
    	double n = 0.01;
    	double z = v+n;
    
    	printf ( "%lf", z );
    

    Ausgabe:

    126.010000



  • Witzig..hab mir das mal angesehen:

    float rfv=(rand()<<16)+rand();
    printf("%f\n",rfv); 
    float rfn=rand()/(float)RAND_MAX;
    printf("%f\n",rfn);   
    float rf=rfv+rfn; 
    printf("%f\n",rfv+rfn);
    printf("%f\n",rf);
    

    Ausgabe:

    2705443.000000
    0.193304
    2705443.193304
    2705443.250000
    

    Also beim speichern in die Variable rf dürfte was flöten gehen



  • Hallo,

    Hab das problem gefunden:

    es muss heißen:
    float rfv
    float rfn
    double rf
    printf("%f",rf)

    oder

    float rfv
    float rfn
    printf("%f",rf+rfv)

    Das Problem lag also im datentyp (ich kann leider nicht erklären warum double nötig ist)

    mfg Christoph



  • Weil double tyischerweise mehr signifikante Dezimalstellen hat als float.



  • Hallo,

    Bin jetzt noch auf ein grundsätzliches Problem meiner Aufgabenstellung gestoßen:
    Ich soll zufällige floats die den gesamten wertebereich von float abdecken erzeugen. Aufgrund der Struktur von float (teils logarithmisch) wäre das aber nicht wie bei anderen datentypen 2^bit (2^32=10 stellige zahl) sondern 1.2E-38 3.4E+38

    Wegen der weiteren Aufgabe (erstellen Sie ein Programm, welches Fließkommazahlen mit maximal 10 signifikaten stellen sortiert) nehme ich an, dass der autor als wertebereich für floats -(2^16) - +(2^16) bzw 2^32 annimmt.

    Wegen:
    float wertebereich=1.2E-38 3.4E+38 genauigkeit=6stellen
    und der angabe 10stellen

    komme ich also nicht wirklich mit seinem gedankengang auf eine linie?!

    Ich hoffe das war nicht zu verwirrend und vl. weiß jemand wie die aufgabe gedacht ist.

    mfg Christoph



  • Hallo,

    Da ich annehme, dass man ohnehin nicht ganz versteht worauf ich hinauswill, bitte ich euch den obigen post einfach zu ignorieren.

    Ich habe mittlerweile einen weg gefunden um floats im gesamten bereich (bis 3.4*10^38) zu generieren:
    float von 0-1 machen und dann mit einer potenz zwischen 10^0 und 10^39 multiplizieren.

    jetzt fällt mir aber auf, dass an die genauigkeit von 6 stellen nochmals 10 stellen mit irgendwelchen zahlen angehängt werden:
    12345600000000000000000000.000000
    wird als
    12345599916402083000000000.000000
    dargestellt.

    wie lässt sich das erklären?

    mfg Christoph



  • Kuldren schrieb:

    Witzig..hab mir das mal angesehen:

    float rfv=(rand()<<16)+rand();
    printf("%f\n",rfv); 
    float rfn=rand()/(float)RAND_MAX;
    printf("%f\n",rfn);   
    float rf=rfv+rfn; 
    printf("%f\n",rfv+rfn);
    printf("%f\n",rf);
    

    Ausgabe:

    2705443.000000
    0.193304
    2705443.193304
    2705443.250000
    

    Also beim speichern in die Variable rf dürfte was flöten gehen

    Tim schrieb:

    Weil double tyischerweise mehr signifikante Dezimalstellen hat als float.

    Hm...Mich würde das jetzt schon interessieren..wieso kann man den float Variablen Werte zuweisen aber dann wird die gespeicherte Addition daraus falsch gespeichert?
    Ich meine aus 0.24234534534 wird von mir aus 0.240000000 (obwohl das auch unlogisch ist) aber wieso wird aus 0.193304 0.25 ?!



  • Kuldren schrieb:

    Hm...Mich würde das jetzt schon interessieren..wieso kann man den float Variablen Werte zuweisen aber dann wird die gespeicherte Addition daraus falsch gespeichert?
    Ich meine aus 0.24234534534 wird von mir aus 0.240000000 (obwohl das auch unlogisch ist) aber wieso wird aus 0.193304 0.25 ?!

    Falls es dich noch interessiert:

    Deine Frage sind an sich 2 Fragen und zwar:

    (1) Warum wird aus 0,19... 0,25 ?
    (2) Warum sinkt die Genauigkeit bei der Addition?

    Zu (1): Du musst bedenken, dass deine Datentypen binär und nicht dezimal abgespeichert/verarbeitet werden, d.h.:
    0.5 => 0.1
    0.25 => 0.01
    0.125 => 0.001
    Also wird dein Wert von 0.19... ganz richtig auf den binären Wert 0.01(=0.25) gerundet.

    Zu (2): Hierzu musst du bedenken, dass deine Variablen(zumindest bei double + float) nicht als Kommazahlen abgespeichert werden, sondern als (ungefähr) Kombination aus (normalisierter) Zahl + einen Exponenten, d.h.
    1000 ist dann 1 * 10^3 (Naja, an sich halt binär, aber das umrechnen spare ich mir mal ;))
    2705443 ist dann 2.705443 * 10^6
    0.193304 ist 1.93305 * 10^(-1)
    bei 2705443.193304 = 2.705443193304 * 10^6 erschöpft sich dann allerdings der Speicherplatz, der in float für die Zahl reserviert ist und es wird gerundet(siehe unter (1)).

    Ich hoffe geholfen zu haben 🙂



  • Danke!


Log in to reply