## random float generator

45 posts / 0 new
Author
Message

Guys, I'm havin' a little bit of trouble generating a random float.  The function is as follows:

```float random_weight(void){
return rand()/RAND_MAX*(float)(2.0) - 1.0;
}
```

The output is as follows:

-0.999992
-0.999979
-0.999991
-0.999973
-0.999971
-0.999971
-0.999972
-0.999990
-0.999973
-0.999976
-0.999994
-0.999979
-0.999982
-0.999987
-0.999978
-0.999993
-0.999985
-0.999998
-0.999997
-0.999985
-0.999973
-0.999978
-0.999973

I'm thinking that it maybe to do with RAND_MAX!

EDITED: I'm trying to generate a float between -1.0 and 1.0

This topic has a solution.
Last Edited: Tue. Jul 14, 2020 - 05:40 PM

I'm amazed you don't get  -1.000000  all the time with the code shown.

rand()/RAND_MAX is integer division, so always 0 (unless rand() == RAND_MAX).

It doesn't get converted to float in this case until you do the multiply by 2.0

You want something more like

```        float f = (float)rand() / RAND_MAX * 2.0f - 1.0f;
```

MrKendo wrote:

`(float)rand() / RAND_MAX * 2.0f - 1.0f;`

Thanks for the reply MrKendo.  I still get the same results.  I'm going to try generating a integer then make that into a float!

You haven't shown how you're printing it.

And you do understand that rand() is not random - don't you...?

Top Tips:

1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...

Fianawarrior wrote:

Thanks for the reply MrKendo.  I still get the same results.  I'm going to try generating a integer then make that into a float!

In that case, either your rand() function isn't the C standard library function (or if you're using C++, don't know in that case), or you aren't showing all that you are doing.

awneil wrote:

And you do understand that rand() is not random - don't you...?

Well, if it's the C standard library function, it's pseudo-random of course.

It may not be very good, and certainly not to be used for cryptographic functions, but with all due respect to OP, if you're creating your own cryptographic functions, good luck with that :)

That's one case where you really don't want to be rolling your own.

Fianawarrior wrote:
I still get the same results.

There's something you are not telling us. And no, there's no way the code you presented in your original message could generate the values you listed, as MrKendo correctly noted. The code you posted is not the code you are running. Unless you provide a more representative example of what's going on in your code, there's no way to say why you still get the same results.

Note BTW, that the granularity of the floating-point values generated by using this method might be too "sparse" for some purposes (depending on the implementation of `rand()`, specifically on its range).

Dessine-moi un mouton

Last Edited: Mon. Jun 22, 2020 - 06:47 PM

I would debug incrementally.

First, return rand()

Then return rand()/RAND_MAX

and so forth

Yes, I know that there are precedence and promotion rules and all that, but to be totally unambiguous, I would write

`( (float)rand()/(float)RAND_MAX )`

It costs your compiled code nothing. And it saves you in situations like this.

Jim

Until Black Lives Matter, we do not have "All Lives Matter"!

Last Edited: Mon. Jun 22, 2020 - 07:04 PM

Okay lads, thanks for the feedback, I have the following working.

```float random_weight(void){

int temp = rand() % 10000;
temp = temp - 5000;

return (float)temp / 5000;
}```

I would like to increase the resolution but when I add more zero's it prints out garbage again.

As you have a habit of posting Cortex A questions is this Cortex A with a hosting OS? If so it should have a /dev/rand or similar that is fed entropy from things luke Ethernet traffic, mouse movement and so on.

I would like to increase the resolution

So generate single digit random numbers, 0 - 9, and concatenate them together.

(Note that the save caveats about randomness apply)

JC

Do you have access to the C++ standard library (C++11 or later)? If so, it provides tools for doing exactly what you want.

```#include <iostream>
#include <random>

int main()
{
auto generator = std::mt19937_64 { std::random_device {}() };

auto distribution = std::uniform_real_distribution<double> { -1.0, 1.0 };

for ( auto i = 0; i < 10; ++i ) {
std::cout << distribution( generator ) << '\n';
} // for
}```

Output:

```0.384381
0.183115
0.634574
-0.103687
0.740283
-0.187781
-0.577465
-0.968228
0.162683
-0.0512241```

github.com/apcountryman/build-avr-gcc: a script for building avr-gcc

github.com/apcountryman/toolchain-avr-gcc: a CMake toolchain for cross compiling for the Atmel AVR family of microcontrollers

apcountryman wrote:

Do you have access to the C++ standard library (C++11 or later)? If so, it provides tools for doing exactly what you want.

```#include <iostream>
#include <random>

int main()
{
auto generator = std::mt19937_64 { std::random_device {}() };

auto distribution = std::uniform_real_distribution<double> { -1.0, 1.0 };

for ( auto i = 0; i < 10; ++i ) {
std::cout << distribution( generator ) << '\n';
} // for
}```

Output:

```0.384381
0.183115
0.634574
-0.103687
0.740283
-0.187781
-0.577465
-0.968228
0.162683
-0.0512241```

Looks good, I'll have a blast at that tomorrow..

Thanks guys for the feedback.

Okay, I really like the c plus-plus version, however it keeps spitting out the same float.  My code is as follows:

```/*
* random_nr.cpp
*
*  Created on: 22 Jun 2020
*      Author: wmjen
*/

#include <random>

#include "random_nr.h"
using namespace std;

float random_weight_(void)
{
auto generator = std::mt19937_64 { std::random_device {}() };
auto distribution = std::uniform_real_distribution<float> { -1.0, 1.0 };

return(distribution( generator ));
}

```

and the header file is as follows:

```/*
* random_nr.h
*
*  Created on: 22 Jun 2020
*      Author: wmjen
*/

#ifndef APPLICATIONS_NEURAL_NETWORK_RANDOM_NR_H_
#define APPLICATIONS_NEURAL_NETWORK_RANDOM_NR_H_

#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif

EXTERNC float random_weight_(void);

#endif /* APPLICATIONS_NEURAL_NETWORK_RANDOM_NR_H_ */```

And the function call is:

```	float test = 0;

for(int i = 0; i < 50; i++){

float temp = random_weight_();

if(temp > 0)
c_printf("\n\r[b]%f", temp);
else
c_printf("\n\r[r]%f", temp);

if(temp > test)
test = temp;
}
c_printf("\n\r[g]%f", test);```

Any suggestions folks?

PS: thanks for looking.

RNGs need seeding with entropy. Do you have a source of entropy?

You are re-initialising generator and distribution on each function call. Make them static.

```float random_weight_pp (void)
{
static auto generator = std::mt19937_64{ std::random_device {}() };

static auto distribution = std::uniform_real_distribution<double>{ -1.0, 1.0 };

return (float)distribution(generator);
}```

C:\Users\Nigel\Documents\Visual Studio 2017\Projects\The_freak\Debug>The_Freak
-0.149776
-0.223296
0.053717
-0.428489
-0.747919
0.841155
0.690961
0.226924
0.920388
0.482196

C:\Users\Nigel\Documents\Visual Studio 2017\Projects\The_freak\Debug>The_Freak
-0.096723
-0.871745
0.601442
0.801830
0.693042
0.324156
0.977126
0.592106
-0.620074
-0.734697

N.Winterbottom wrote:
entropy

Hi M.Winterbottom, that correction now gives random numbers, however they are now the same results when I reboot the system.  As clawson says, I need to have entropy? maybe my c plus-plus is not setup correctly!

In #4, I wrote:
you do understand that rand() is not random - don't you...?

In #16, Fianawarrior wrote:
the same results when I reboot the system

That'll be a "No", then.

Top Tips:

1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...

General question.... If you have a float width of, say, 32 bits, and generate a random bit stream which you truncate into 32 bit chunks. Can you simply use that value as if it were a float?

I'm aware of the concept of NAN but havent looked into how a compiler like GCC formats floats and whether there are any invalid codes.

Using a physical source would make for much better random numbers.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

Last Edited: Tue. Jun 23, 2020 - 05:54 AM

Brian,

Interesting question. You can kind of "try that out a bit" if you use something like:

https://www.h-schmidt.net/FloatConverter/IEEE754.html

If you type any 8 digit (possibly leading 0 padded) hex value into the "Hexadecimal representation" box it will show you how that is interpreted as a float.

As you say there are "special" values like NaN and Inf but apart from those I *think* most 32 bit values are valid.

Ah I see it even supports the "special values":

The possible implication of that is that all other 32 bit patterns are valid float ?

Last Edited: Tue. Jun 23, 2020 - 08:17 AM

Cliff,

No. From that link, any number 0b 0 1111111 1xxx... is infinity if all the remaining x are 0, but NaN if *any* of the x are 1.

So it looks like - at least on that interpretation - that any 32-bit value is a valid float unless the top nine bits are ones, or the top bit is zero and the next eight are ones. So there's a 2/512 chance you're going to get either a NaN (most likely) or a +/- infinity. But easily fixed by trapping those values out.

Neil

Last Edited: Tue. Jun 23, 2020 - 08:37 AM

Brian Fairchild wrote:
If you have a float width of, say, 32 bits, and generate a random bit stream

But that's hardly a truly random number because there are more discrete floating point numbers between 0 & 1 than exist in the rest of the FP range. This will skew the distribution significantly.

Last Edited: Tue. Jun 23, 2020 - 10:29 AM

Of the 32 bit float maybe keep the first 9 bits unchanging and just vary the last 23 then?

Generate a random integer in the range -2**24..2**24 .

Multiply by 2**-24 .

All values will be exactly representable.

Note that including both endpoints requires 2**25+1 possible integers.

I do not know the requirements of neural net code.

Is this really being done on an AVR?

Do you really want it non-repeatable?

Non-repeatability is a primary source of debugging hell.

Iluvatar is the better part of Valar.

N.Winterbottom wrote:

But that's hardly a truly random number because there are more discrete floating point numbers between 0 & 1 than exist in the rest of the FP range. This will skew the distribution significantly.

While it is true that the distribution will be skewed, I don't see why it is "hardly a truly random number". The term "random number" never implies uniform distribution. There's no uniform distribution requirement for the number to be "truly random". The only reason we are assuming uniform distribution in this case is because it follows from the original example.

In any case, properties of IEEE754 floating point representation make it impossible to generate a uniformly distributed floating-point value in the full range of the type, simply because the "stepping" changes constantly as we move away from 0. Uniform distribution is only possible if you keep the exponent fixed.

Dessine-moi un mouton

Last Edited: Tue. Jun 23, 2020 - 04:38 PM

AndreyT wrote:
While it is true that the distribution will be skewed, I don't see why it is "hardly a truly random number". The term "random number" never implies uniform distribution. There's no uniform distribution requirement for the number to be "truly random".
Isn't there a Martin Gardner "absurdity" in one of his books that describes something along these lines...

A perfect random generator over time would have a uniform spread of samples over the range but if a random system had such a uniform spread then it would be predictable and therefore not "random". As such random does not exist!

(must dig out the books (/ or google?) to remind myself of the actual argument)

Ahhh, the great Martin Gardner. For a  long time, HE was the  reason I read "Scientific American".

Jim

Until Black Lives Matter, we do not have "All Lives Matter"!

clawson wrote:

(must dig out the books (/ or google?) to remind myself of the actual argument)

Certainly. Arguments like that are often misunderstood and therefore misquoted, which sometimes is the only source of perceived absurdity.

One can argue that, if one takes a random number generator, tests it and confirms that it is indeed a random number generator, then it is not random anymore. Since anything that behaves as expected is not truly random. It probably makes a nice philosophical sophism/paradox/joke, but definitely falls outside the scope of this topic.

Dessine-moi un mouton

AndreyT wrote:

clawson wrote:

(must dig out the books (/ or google?) to remind myself of the actual argument)

Certainly. Arguments like that are often misunderstood and therefore misquoted, which sometimes is the only source of perceived absurdity.

One can argue that, if one takes a random number generator, tests it and confirms that it is indeed a random number generator, then it is not random anymore. Since anything that behaves as expected is not truly random. It probably makes a nice philosophical sophism/paradox/joke, but definitely falls outside the scope of this topic.

Jesus lads, only need a random number, not a feckin' philosophical lecture.  Anyway, I found method to seed/srand he system.  See below for the c version and the c plus-plus version.

```float random_weight_ (void){

char sys_time[3];

sys_time[0] = NMEA_GPRMC.UTC_Time[6];
sys_time[1] = NMEA_GPRMC.UTC_Time[7];
sys_time[2] = NMEA_GPRMC.UTC_Time['\0'];

static char seed = 0;
static auto generator = std::mt19937_64{
std::random_device {}()
};

// include entropy into the random number generator
generator.seed(kernel_core.kernel_stamp + seed++ + atoi(&sys_time[0]));

static auto distribution = std::uniform_real_distribution<double>{ -1.0, 1.0 };

return (float)distribution(generator);
}```
```float random_weight(void){

char sys_time[3];

sys_time[0] = NMEA_GPRMC.UTC_Time[6];
sys_time[1] = NMEA_GPRMC.UTC_Time[7];
sys_time[2] = NMEA_GPRMC.UTC_Time['\0'];

static char seed = 0;

// include entropy into the random number generator
srand(kernel_core.kernel_stamp + seed++ + atoi(&sys_time[0]));

int temp = rand() % 10000;
temp = temp - 5000;

return (float)temp / 5000;
}```

However, when I ported the routines into the RTOS it spits out garbage, see below:

-2.000002
-0.000000
-0.000000
-0.000000
-2.000002
-2.000002
2.681562e+154
-2.000000
2.681564e+154
0.000000
-0.000000
0.000000
0.000000

Is there a clue in the numbers generated???/

Fianawarrior wrote:

```	sys_time[2] = NMEA_GPRMC.UTC_Time['\0'];
```

What exactly is this line supposed to do?

And again, as you have been told already, `srand`-ing the generator before each request for a random number is a bad idea. This will easily lead to the same time value used in multiple contiguous calls and therefore the same "random" number produced by `rand()`.

Dessine-moi un mouton

Last Edited: Tue. Jun 23, 2020 - 06:26 PM

Fianawarrior wrote:

Is there a clue in the numbers generated???/

Yes.

You have at least one bug in code you haven't shown.

AndreyT wrote:

Fianawarrior wrote:

```	sys_time[2] = NMEA_GPRMC.UTC_Time['\0'];
```

What exactly is this line supposed to do?

And again, as you have been told already, `srand`-ing the generator before each request for a random number is a bad idea. This will easily lead to the same time value used in multiple contiguous calls and therefore the same "random" number produced by `rand()`.

Hi AndreyT, yes, that was an error, it should have read:

`sys_time[2] = '\0';`

Any how, the same garbage comes up, this only occurs when in he kernel.  I have tried omitting the "srand" and "seed" without joy.

PS: to avoid srand generating the same seed and therefore duplicating a number I have the varible seed that increments each call.

Okay, multiplying the random float by 1000,000 gives the following:

-1711960928
2005088530
-569786299
2128868656
154183397
-1251323615
-1664280325
-872690152
126657474
422168523
1183936932
1803007741

`c_printf("\n\r[b]%i", random_weight_() * 1000000);`
```float random_weight_ (void){

char sys_time[3];

sys_time[0] = NMEA_GPRMC.UTC_Time[6];
sys_time[1] = NMEA_GPRMC.UTC_Time[7];
sys_time[2] = '\0';

static char seed = 0;
static auto generator = std::mt19937_64{
std::random_device {}()
};

// include entropy into the random number generator
generator.seed((int)kernel_core.kernel_stamp + seed++ + atoi(&sys_time[0]));

static auto distribution = std::uniform_real_distribution<float>{ -1.0, 1.0 };

return (float)distribution(generator);
}```

Fianawarrior wrote:

c_printf("\n\r[b]%i", random_weight_() * 1000000);

random_weight_ returns float, multiplying that by 1000000 means it is still float, but you are printing with %i .

In C, this is undefined behaviour. I Imagine it's not good in C++ either but I'm not familiar with C++ rules.

Going back to the C version, why have you not printed out the values returned from rand() which is a straightforward int.

That would be a good place to start.

I have a sneaky feeling that the problem is in the custom software package.  I'll soon find out.

Here are some random floats for you:

Top Tips:

1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...

awneil wrote:

Here are some random floats for you:

awneil, what ever floats your boats.

Can you generate a sequence of random bits?

If so, you should be able to get whatever else you want.

Iluvatar is the better part of Valar.

skeeve wrote:

Can you generate a sequence of random bits?

If so, you should be able to get whatever else you want.

Hi skeeve, what about a cpu register or a floating adc input?

Fianawarrior wrote:

Hi skeeve, what about a cpu register or a floating adc input?

https://dannyelectronics.wordpre...

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

Final code:

```float random_weight_ (void){

char sys_time[7];

sys_time[0] = NMEA_GPRMC.UTC_Time[0];
sys_time[1] = NMEA_GPRMC.UTC_Time[1];
sys_time[2] = NMEA_GPRMC.UTC_Time[3];
sys_time[3] = NMEA_GPRMC.UTC_Time[4];
sys_time[4] = NMEA_GPRMC.UTC_Time[6];
sys_time[5] = NMEA_GPRMC.UTC_Time[7];

sys_time[6] = '\0';

int seed = rand();
static auto generator = std::mt19937_64{
std::random_device {}()
};

// include entropy into the random number generator
generator.seed((int)kernel_core.kernel_stamp + seed + atoi(&sys_time[0]));

static auto distribution = std::uniform_real_distribution<float>{ -1.0, 1.0 };

return (float)distribution(generator);
}```

However, when I enter my RTOS the floating variables are trashed.  I was away for a trip today so I never got to look at the problem but if any freaks can think of something that my cause it please feel free to post.

Wm.

Last Edited: Thu. Jun 25, 2020 - 11:00 PM

Fianawarrior wrote:
However, when I enter my RTOS the floating variables are trashed.
What floating point values?

-1 and 1?

According to the definition of uniform_real_distribution, yours would include -1, but not +1 .

Is that what you want?

In float, the range { -1 } is the the same as the range [-1, -1+2**-24) and its probability should be 2**-25 .

Is that what happens?  Is that what you want?

Deciding what you want to happen at the boundaries can be important.

Note that 2**25 is less than 34 million.

On some platforms, getting statistics would be practical.

Iluvatar is the better part of Valar.

Last Edited: Fri. Jun 26, 2020 - 02:12 PM
This reply has been marked as the solution.
```float random_weight_ (void){

extern struct NMEAGPRMC NMEA_GPRMC;

// compute time for seed, entropy
char sys_time[7];

sys_time[0] = NMEA_GPRMC.UTC_Time[0];
sys_time[1] = NMEA_GPRMC.UTC_Time[1];

sys_time[2] = NMEA_GPRMC.UTC_Time[3];
sys_time[3] = NMEA_GPRMC.UTC_Time[4];

sys_time[4] = NMEA_GPRMC.UTC_Time[6];
sys_time[5] = NMEA_GPRMC.UTC_Time[7];
sys_time[6] = '\0';

char sys_date[7];

// compute date for seed, entropy
sys_date[0] = NMEA_GPRMC.UTC_Date[0];
sys_date[1] = NMEA_GPRMC.UTC_Date[1];

sys_date[2] = NMEA_GPRMC.UTC_Date[3];
sys_date[3] = NMEA_GPRMC.UTC_Date[4];

sys_date[4] = NMEA_GPRMC.UTC_Date[6];
sys_date[5] = NMEA_GPRMC.UTC_Date[7];
sys_date[6] = '\0';

// A Mersenne Twister pseudo-random generator of 64-bit numbers with a state size of 19937 bits.
static auto generator = std::mt19937_64{

std::random_device {}()
};

static unsigned int seed = 0;

// include entropy into the random number generator
generator.seed(std::stoi(&sys_time[0]) + std::stoi(&sys_date[0]) + seed++);

static auto distribution = std::uniform_real_distribution<float>{ -1.0, 1.0 };

// generate random number
return distribution(generator);
}```

Reading the following about " What is a reliable electronic circuit to feed into an ADC to generate true random numbers based on junction quantum effects? I have tried, but all suffered from EM 60Hz interference.

Roy's answer is similar to a "Hororan" (AoE) where the ADC is an analog comparator (1-bit ADC)

The Art of Electronics 3rd Edition | by Horowitz and Hill

[pages 982 and 983]

13.14.7 "True" random noise generators

"Dare to be naïve." - Buckminster Fuller