Forum: Compiler & IDEs Arduino random function type casts


von Martin O. (ossi-2)


Lesenswert?

Ich verstehe nicht, was bei folgendem Programm passiert. Da wo 
random(10)-5 negativ wird, werden grosse positive Werte ausgegeben. Bei 
allen auskommentierten Versionen ist das nicht der Fall. Für mich sind 
die grossen positiven Werte nicht erklärbar, zumal es bei anderen 
Schreibweisen keine Probleme gibt. Das ganze läuft auf nem teensy 36.

Hier das Programm zusammen mit der Ausgabe (weiter unten).
1
long RANDOM(int d){
2
  return random(d) ;
3
  }
4
  
5
void setup() {
6
  Serial.begin(115200); 
7
  delay(2000) ;
8
  Serial.print("Hello World 1\n"); 
9
  randomSeed(1);
10
 
11
  for(int k=0 ; k<20 ; k++){ 
12
     
13
     double x=random(10)-5 ; 
14
     
15
     //double x=RANDOM(10)-5 ;
16
     //double x=(int)random(10)-5 ;
17
     //int i=random(10)-5 ; double x=(double)i ;
18
     //long i=random(10)-5 ; double x=(double)i ;
19
     //double x=(long)random(10)-5 ;
20
     Serial.printf("%5d  %15.5f  \n",k,x) ;
21
   }
22
  }
23
24
void loop(){
25
  }  
26
27
/*
28
  Hello World 1
29
    0          2.00000  
30
    1          4.00000  
31
    2  4294967294.00000  
32
    3          3.00000  
33
    4  4294967291.00000  
34
    5  4294967293.00000  
35
    6  4294967295.00000  
36
    7          3.00000  
37
    8  4294967294.00000  
38
    */

von Eric B. (beric)


Lesenswert?

Was liefert random() für ein Wert zurück: double, (long) (unsigned) int?
Und was passiert bei
1
double x = random(10) - 5.0lf;

von Martin O. (ossi-2)


Lesenswert?

double x=random(10)-5.0f ;

liefert die richtigen (negativen) Werte. 5.0lf ist als Typ nicht 
bekannt.
random liefert laut Dokumentation einen long Wert.

von Oliver S. (oliverso)


Lesenswert?

Der Doku nach ist der Returntyp von random() ein long.

Damit sollte das Ergebnis von random(10)-5 (long - int) auch ein long 
sein, und damit auch negative Werte darstellen können, die dann nach 
float umgewandelt werden.

Oliver

von Oliver S. (oliverso)


Lesenswert?

Mangels Arduino und mangels Serial.printf lässt sich dein Code bei mir 
nicht ausprobieren. Ein Test in Tinkercad mit folgendem Code
1
...
2
    double x=random(10)-5 ; 
3
    
4
    Serial.print(k);
5
    Serial.print(", ");
6
    Serial.print(x) ;
7
    Serial.print('\n');
8
...

liefert aber das gewünschte Ergebnis:
1
Hello World 1
2
0, 2.00
3
1, 4.00
4
2, -2.00
5
3, 3.00
6
4, -5.00
7
5, -3.00
8
6, -1.00
9
7, 3.00
10
8, -2.00
11
9, 4.00
12
10, -5.00
13
11, 0.00
14
12, -3.00
15
13, -3.00
16
14, 2.00
17
15, -2.00
18
16, 2.00
19
17, 4.00
20
18, -5.00
21
19, -3.00

Woher kommt denn deine printf-Funktion?

Oliver

: Bearbeitet durch User
von Eric B. (beric)


Lesenswert?

Martin O. schrieb:
> double x=random(10)-5.0f ;
>
> liefert die richtigen (negativen) Werte. 5.0lf ist als Typ nicht
> bekannt.

lf wäre 'long float', also double, aber wenn's mit f funktioniert...

> random liefert laut Dokumentation einen long Wert.

Dann sieht's danach aus, dass die Konvertierung von long nach double 
nicht funktioniert für negative Zahlen.
1
long test = -1;
2
printf("%f", (double) test);
 müsste dann auch das falsche Ergebnis geben.

von Markus F. (mfro)


Lesenswert?

Martin O. schrieb:
> random liefert laut Dokumentation einen long Wert.

Das kann sein. In den Quellen (teensy3/WProgram.h) steht aber (mehrfach 
überladen) was anderes:
1
int32_t random(void);
2
uint32_t random(uint32_t howbig);
3
int32_t random(int32_t howsmall, int32_t howbig);

Unser Kandidat geht also mit einem uint32_t um.

von Markus F. (mfro)


Lesenswert?

... übrigens ist das zwar Arduino-mäßig nicht verkehrt, aber 
Kinetis-mäßig Murks: der Kinetis hat nämlich einen (ziemlich guten) 
Hardware-RNG:

https://forum.pjrc.com/threads/48745-Teensy-3-6-Random-Number-Generator

von Martin O. (ossi-2)


Lesenswert?

@Oliver S.: Ja, so sollte es meinem Verständnis nach auch sein. Ist es 
aber nicht. Auf einem Arduino Uno tritt der Effekt nicht auf.

von Oliver S. (oliverso)


Lesenswert?

Markus F. schrieb:

> In den Quellen (teensy3/WProgram.h) steht aber (mehrfach
> überladen) was anderes:
> int32_t random(void);
> uint32_t random(uint32_t howbig);
> int32_t random(int32_t howsmall, int32_t howbig);
>
> Unser Kandidat geht also mit einem uint32_t um.

Tja, und da wundert sich einige, warum das Zeugs keiner ernst nimmt.

Oliver

von Martin O. (ossi-2)


Lesenswert?

Mit dem uint32_t wirds verständlich. Dass random einen long liefert habe 
ich der Arduino Doku entnommen, denn angeblich ist Teensy zum Arduino 
kompatibel. Stimmt wohl nicht so ganz.

Besten Dank!

von Markus F. (mfro)


Lesenswert?

Martin O. schrieb:
> Dass random einen long liefert ...

Martin O. schrieb:
> Stimmt wohl nicht so ganz.

Stimmt wohl. Aber nur, wenn man's ohne (oder mit zwei) Parameter(n) 
aufruft.

Dann kommt ein int32_t zurück und das ist beim Kinetis identisch zu 
long.

von Rolf M. (rmagnus)


Lesenswert?

Eric B. schrieb:
> Martin O. schrieb:
>> double x=random(10)-5.0f ;
>>
>> liefert die richtigen (negativen) Werte. 5.0lf ist als Typ nicht
>> bekannt.
>
> lf wäre 'long float', also double, aber wenn's mit f funktioniert...

Man braucht ja nun auch nicht unbedingt einen double, um einen 
ganzzahligen Wert im Bereich -5 bis 5 darzustellen.

von Eric B. (beric)


Lesenswert?

Rolf M. schrieb:
> Man braucht ja nun auch nicht unbedingt einen double, um einen
> ganzzahligen Wert im Bereich -5 bis 5 darzustellen.

Stimmt, aber der TO wollte das so. Er schrieb ja:

> double x=random(10)-5 ;

von Rolf M. (rmagnus)


Lesenswert?

Das ist schon klar. Ich bezog mich auf den Satz:

Eric B. schrieb:
> lf wäre 'long float', also double, aber wenn's mit f funktioniert...

5.0f funktioniert bei diesem Wertebereich natürlich. Das lf bringt da 
keinen Vorteil.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.