Random function in expression gives wrong values

Status
Not open for further replies.

ossi

Well-known member
Running the code shown below on a Teensy 36 gives big integers as result where negative values should occur. Output of the code is shown below also. If the line with "..random.." is replaced by one of the lines given below this error does not occur. If the code is run on an Arduino Uno the error also does not occur. Any idea what happens? Could one of you test if the error occurs also at his site?

Code:
void setup() {
  Serial.begin(9600); 
  delay(2000) ;
  Serial.print("Hello World 1\n"); 
  randomSeed(1);
  for(int k=0 ; k<20 ; k++){ 
     double x=random(10)-5 ; 
     Serial.printf("%5d  %15.5f  \n",k,x) ;
     }
  }

// these lines work:
//double x=random(10)-5.0f ; 
//double x=(int)random(10)-5 ;
//int i=random(10)-5 ; double x=(double)i ;
//long i=random(10)-5 ; double x=(double)i ;
//double x=(long)random(10)-5 ;


void loop(){
  }  

Program output is
  Hello World 1
    0          2.00000  
    1          4.00000  
    2  4294967294.00000  
    3          3.00000  
    4  4294967291.00000  
    5  4294967293.00000  
    6  4294967295.00000  
    7          3.00000  
    8  4294967294.00000
 
Why would you waste RAM and CPU cycles for a float with double precision (double x), when a simple int8_t is more than sufficient? All these type conversions which you do waste time and memory for nothing. And you get type cast errors as you found out yourself...
 
The example comes from a FFT program where I wanted to initialize a double-vector with random data.
in my original example
double x[NFFT]
x[k]=random(10)-5 ;
the occuring big numbers can not be explained by a cast, as far as I understand. The other versions of the line work as I expected. The original line works not as expected, and I am still searching for an explanation.
 
The huge numbers ARE cast errors, they are the binary 2-complements in a 32bit structure. Subtracting 2^32 (4 294 967 296) from these gives the expected -2, -5, -3, -1, and -2.

On Cortex M4F processors (Teensy 3.5 and 3.6), the FPU does only support single precision floats in hardware. Double precision will have the whole mathematics emulated in software which is much, much slower compared to using the FPU. You should thus consider defining your vector as float x[NFFT]. The precision of single floats is still sufficient to push rounding errors below -120dB.
 
I would have expected the following for the line x=random(10)-5 :
random returns a long (says the documentation), thus the 5 should also be treated as a long. Then the difference random(10)-5 should be computed as a long. Then the long should be converted to a double ( a float gives the same behaviour). In this process I can not see where there can happen a cast error. Can you explain where the process differs from my view.

I used a double in my FFT program just to measure the speed of the CMSIS version, a self coded float version, and a self coded double version. So I really wanted the double in this place.
 
The issue has been solved in another forum: random(maxval) returns an uint32_t value, not a long as specified for Arduino
The types for the teensy are
int32_t random(void);
uint32_t random(uint32_t howbig);
int32_t random(int32_t howsmall, int32_t howbig);
 
So, random returns an unsigned value. Which explains the overflow after the subtraction when the result is expected to be negative. Which goes conform with my interpretion of the high values above.
 
Status
Not open for further replies.
Back
Top