generate random float number in C# - c#

How to generate 100 randoms float between -1 and 1 with the main distriburion between -0.1 to 0.1 (90 % of float numbers must be between -0.1 to 0.1).
Currently I use which is not exactly what i want
for (int counter = 0; counter < 100; counter++)
{
randomnum = 0f;
randomnum = Convert.ToSingle(randomvalues.NextDouble() / 10);
storerandomvalues1[counter] = randomnum;
}
Any idea?

This should work. It generates one random number to choose whether you're in the range -0.1,0.1 and then a second which is expanded to the actual range you want it in. You could do it with just one random double, but that would make it easier to get the code wrong, and harder to read (all for a tiny performance improvement).
for (var counter = 0; counter < 100; counter++)
{
int selector = randomvalues.Next(10); // 0 <= selector < 10
double randomnum;
if (selector < 9)
{
randomnum = randomvalues.NextDouble() * 0.2 - 0.1;
}
else
{
randomnum = randomvalues.NextDouble() * 1.8 - 0.9;
randomnum += Math.Sign(randomnum) * 0.1;
}
storerandomvalues1[counter] = (float)randomnum;
}

As I said in a comment, there are an infinite number of possible solutions. Two possible solutions follow:
A Normal (aka Gaussian) distribution with a mean of 0 and a standard
deviation of 0.06079 will have 90% of its outcomes between -0.1 and
+0.1, so generate a standard normal and multiply it by 0.06079. Technically you should check whether the absolute value exceeds 1,
but that corresponds to getting outcomes at 16 sigma -- it's just
not going to happen.
However, you might not like solution that because it won't span
the entire range in practice. A variant which will is to generate
X as described in the prior paragraph, and if X < -0.1, replace
it with a Uniform(-1, -0.1). Similarly, if X > 0.1, replace it
with a Uniform(0.1, 1).
I implemented both of these, generated 100,000 values, and here are the histograms:
Note that the 5th and 95th quantiles are -0.0998 and +0.09971, respectively, effectively -0.1 and +0.1 to within sampling error.

use log function, Generate floats between 1 and 10, then take the log base 10 of the result. then randomly change the sign.

Try this, it should work...
Random rnd = new Random();
for (int counter = 0; counter < 100; counter++)
{
storerandomvalues1[counter]=(2*rnd.NextDouble())-1; // Exact Sample() is protected so u can use NextDouble()
}

Related

How can I modify this random double generator to return more zeros

I have this extension method that, given a minimum and maximum double, generates a double between them.
public static double NextDouble(this Random random, double minValue, double maxValue)
{
return random.NextDouble() * (maxValue - minValue) + minValue;
}
I mainly use this extension method to generate random dollar amounts, and sometimes 0 dollars is an OK value! That being said, I need to increase the odds of returning a 0. More specifically, if I try the following:
Random rando = new Random();
List<double> doubles = new List<double>();
for (int i = 0; i < 100000; i++)
{
double d = rando.NextDouble(0, .25);
Console.WriteLine(d.ToString());
}
I don't get a single zero.
A less than ideal solution I thought of is I can just catch every value less than 1 and return 0 instead.
public static double NextDouble(this Random random, double minValue, double maxValue)
{
double d = random.NextDouble() * (maxValue - minValue) + minValue;
if (d < 1)
{
return 0;
}
return d;
}
This obviously removes the ability to return values less than 1 (.25, .50, .125, etc..). I'm looking for some clever ways around this!
A simple way of approaching this is to generate two random numbers: the first to determine if you return 0, and if not, you return the second number. Say for instance you want a 5% chance of returning zero. Generate a random integer between 1 and 100 inclusive, and if its 5 or less, simply return zero.
if (minValue <= 0.0 && 0.0 <= maxValue)
{
var shouldWeReturnZero = rando.Next(1, 101) <= 5;
if (shouldWeReturnZero)
return 0;
}
Otherwise, generate the actual random number using the code you already have.
What you might want to do is instead of generating a random double, generate a random int and let it represent cents.
that way, 0 will be just as likely as any other amount of cents. When showing them to the user, you can display them as dollars.
var random = new Random();
for (var i = 0; i < 1000; i++)
{
var cents = random.Next(0, 200);
Console.WriteLine("Dollar amount: ${0:0}.{1:00}", cents / 100, cents % 100);
}
Console.ReadKey(false);
So the reason why you are getting no zeroes is that the probability of getting an absolute zero when generating a double is very very very unlikely. If you have a 32-bit floating number, the probability of getting a zero is somewhere around the number 1/2^32. If you want to know more, check out https://en.wikipedia.org/wiki/Single-precision_floating-point_format and how floating numbers are constructed from memory.
In your case I would create a floor-function that instead of flooring to integers, it does so in steps of 0.25. So, a floor function takes any floating number and removes the decimals so what's left is an integer, for example from 1.7888 to 1. You want something that is a bit less rough, so if you insert a value of 1.7888, it would spit out 1.75.

Multiple iterations of random double numbers tend to get smaller

I am creating a stock trading simulator where the last days's trade price is taken as opening price and simulated through out the current day.
For that I am generating random double numbers that may be somewhere -5% of lastTradePrice and 5% above the lastTradePrice. However after around 240 iterations I see how the produced double number gets smaller and smaller closing to zero.
Random rand = new Random();
Thread.Sleep(rand.Next(0,10));
Random random = new Random();
double lastTradeMinus5p = model.LastTradePrice - model.LastTradePrice * 0.05;
double lastTradePlus5p = model.LastTradePrice + model.LastTradePrice * 0.05;
model.LastTradePrice = random.NextDouble() * (lastTradePlus5p - lastTradeMinus5p) + lastTradeMinus5p;
As you can see I am trying to get random seed by utilising Thread.sleep(). And yet its not truly randomised. Why is there this tendency to always produce smaller numbers?
Update:
The math itself is actually fine, despite the downwards trend as Jon has proven it.
Getting random double numbers between range is also explained here.
The real problem was the seed of Random. I have followed Jon's advice to keep the same Random instance across the thread for all three prices. And this already is producing better results; the price is actually bouncing back upwards. I am still investigating and open to suggestions how to improve this. The link Jon has given provides an excellent article how to produce a random instance per thread.
Btw the whole project is open source if you are interested. (Using WCF, WPF in Browser, PRISM 4.2, .NET 4.5 Stack)
The TransformPrices call is happening here on one separate thread.
This is what happens if I keep the same instance of random:
And this is generated via RandomProvider.GetThreadRandom(); as pointed out in the article:
Firstly, calling Thread.Sleep like this is not a good way of getting a different seed. It would be better to use a single instance of Random per thread. See my article on randomness for some suggested approaches.
However, your code is also inherently biased downwards. Suppose we "randomly" get 0.0 and 1.0 from the random number generator, starting with a price of $100. That will give:
Day 0: $100
Day 1: $95 (-5% = $5)
Day 2: $99.75 (+5% = $4.75)
Now we can equally randomly get 1.0 and 0.0:
Day 0: $100
Day 1: $105 (+5% = $5)
Day 2: $99.75 (-5% = $5.25)
Note how we've got down in both cases, despite this being "fair". If the value increases, that means it can go down further on the next roll of the dice, so to speak... but if the value decreases, it can't bounce back as far.
EDIT: To give an idea of how a "reasonably fair" RNG is still likely to give a decreasing value, here's a little console app:
using System;
class Test
{
static void Main()
{
Random random = new Random();
int under100 = 0;
for (int i = 0; i < 100; i++)
{
double price = 100;
double sum = 0;
for (int j = 0; j < 1000; j++)
{
double lowerBound = price * 0.95;
double upperBound = price * 1.05;
double sample = random.NextDouble();
sum += sample;
price = sample * (upperBound - lowerBound) + lowerBound;
}
Console.WriteLine("Average: {0:f2} Price: {1:f2}", sum / 1000, price);
if (price < 100)
{
under100++;
}
}
Console.WriteLine("Samples with a final price < 100: {0}", under100);
}
}
On my machine, the "average" value is always very close to 0.5 (rarely less then 0.48 or more than 0.52) but the majority of "final prices" are always below 100 - about 65-70% of them.
Quick guess: This is a math-thing, and not really related to the random generator.
When you reduce the trade price by 5%, you get a resulting value that is lower than that which you began with (obviously!).
The problem is that when you then increase the trade price by 5% of that new value, those 5% will be a smaller value than the 5% you reduced by previously, since you started out with a smaller value this time. Get it?
I obviously haven't verified this, but I have strong hunch this is your problem. When you repeat these operations a bunch of times, the effect will get noticeable over time.
Your math should be:
double lastTradeMinus5p = model.LastTradePrice * 0.95;
double lastTradePlus5p = model.LastTradePrice * (1/0.95);
UPDATE: As Dialecticus pointed out, you should probably use some other distribution than this one:
random.NextDouble() * (lastTradePlus5p - lastTradeMinus5p)
Also, your range of 5% seems pretty narrow to me.
I think this is mainly because the random number generator you are using is technically pants.
For better 'randomness' use RNGCryptoServiceProvider to generate the random numbers instead. It's technically a pseudo-random number generated, but the quality of 'randomness' is much higher (suitable for cryptographic purposes).
Taken from here
//The following sample uses the Cryptography class to simulate the roll of a dice.
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
class RNGCSP
{
private static RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
// Main method.
public static void Main()
{
const int totalRolls = 25000;
int[] results = new int[6];
// Roll the dice 25000 times and display
// the results to the console.
for (int x = 0; x < totalRolls; x++)
{
byte roll = RollDice((byte)results.Length);
results[roll - 1]++;
}
for (int i = 0; i < results.Length; ++i)
{
Console.WriteLine("{0}: {1} ({2:p1})", i + 1, results[i], (double)results[i] / (double)totalRolls);
}
rngCsp.Dispose();
Console.ReadLine();
}
// This method simulates a roll of the dice. The input parameter is the
// number of sides of the dice.
public static byte RollDice(byte numberSides)
{
if (numberSides <= 0)
throw new ArgumentOutOfRangeException("numberSides");
// Create a byte array to hold the random value.
byte[] randomNumber = new byte[1];
do
{
// Fill the array with a random value.
rngCsp.GetBytes(randomNumber);
}
while (!IsFairRoll(randomNumber[0], numberSides));
// Return the random number mod the number
// of sides. The possible values are zero-
// based, so we add one.
return (byte)((randomNumber[0] % numberSides) + 1);
}
private static bool IsFairRoll(byte roll, byte numSides)
{
// There are MaxValue / numSides full sets of numbers that can come up
// in a single byte. For instance, if we have a 6 sided die, there are
// 42 full sets of 1-6 that come up. The 43rd set is incomplete.
int fullSetsOfValues = Byte.MaxValue / numSides;
// If the roll is within this range of fair values, then we let it continue.
// In the 6 sided die case, a roll between 0 and 251 is allowed. (We use
// < rather than <= since the = portion allows through an extra 0 value).
// 252 through 255 would provide an extra 0, 1, 2, 3 so they are not fair
// to use.
return roll < numSides * fullSetsOfValues;
}
}
According to your code, I can derive it in a simpler version as below:
Random rand = new Random();
Thread.Sleep(rand.Next(0,10));
Random random = new Random();
double lastTradeMinus5p = model.LastTradePrice * 0.95; // model.LastTradePrice - model.LastTradePrice * 0.05 => model.LastTradePrice * ( 1 - 0.05 )
double lastTradePlus5p = model.LastTradePrice * 1.05; // model.LastTradePrice + model.LastTradePrice * 0.05 => model.LastTradePrice * ( 1 + 0.05 )
model.LastTradePrice = model.LastTradePrice * ( random.NextDouble() * 0.1 + 0.95 ) // lastTradePlus5p - lastTradeMinus5p => ( model.LastTradePrice * 1.05 ) - ( model.LastTradePrice * 0.95 ) => model.LastTradePrice * ( 1.05 - 0.95)
So you are taking model.LastTradePrice times a fractional number(between 0 to 1) times 0.1 which will always decrease more to zero, but increase less to 1 !
The litle fraction positive part comes because of the + 0.95 part with the zero-tending random.NextDouble() * 0.1

Find maximum value of a continuous function at a specific resolution

Imagine having a function that is continuous over a range [0.0,n]. Are there any algorithms to find the maximum value of the function given a minimum step size s more quickly than simple iteration? The simple iteration is straightforward to program but the time complexity grows when n / s is large.
double maxValue = 0;
double maxValueX = 0;
double s = 0.1 * n;
for (double x = 0.0; x <= n; x += s)
{
double value = someFunction(x);
if(value > maxValue) {
maxValue = value;
maxValueX = x;
}
}
I have tried this approach which is much quicker, but don't know if it will get stuck on local maximums.
double min = 0;
double max = n;
int steps = 10;
increment = (max - min) / steps;
while (increment > s)
{
double maxValue = 0;
double maxValueX = X;
for (double x= min; x <= max; x+= increment)
{
double value = someFunction(x);
if(value > maxValue) {
maxValue = value;
maxValueX = x;
}
}
min = Math.Max(maxValueX - increment, 0.0);
max = Math.Min(maxValueX + increment, n);
increment = (max - min) / steps;
}
Suppose there was such an algorithm, that is, an algorithm that can find the maximum of an approximation of a continuous function without looking at every point of the approximation.
Now choose a positive integer n and choose any finite sequence of n doubles you care to name. There are infinitely many continuous functions such that f(n) is equal to the nth double in the sequence, and smaller than or equal to the largest of them everywhere. Choose one of them.
Now use your algorithm to find the largest double of the n doubles. By assumption, it examines fewer than n of the doubles. Let's suppose it examines all of them except the kth double.
Now suppose we create a new sequence identical to the first one except that the kth double is the maximum. Is the algorithm magical, that when given an input that it does not read, it changes its output?
Now is it clear why there is no such algorithm? If you want to find the longest piece of string in the drawer, you're going to have to look at all of them.
The continuity of the function doesn't help you at all. All continuity gives you is a guarantee that given a point on the function, you can find another point on the function that is as close to the first point as you like. That tells you nothing about the maximum value taken on by the function. (Well, OK, it tells you something. On a closed bounded interval it implies that a maximum exists, which is something. But it doesn't help you find it.)
Given the function you are talking about is code, then no, that function could return any arbitrary maximum at any point.
If you can make assumptions about the function ( like maximum rate of change ) then you could optimize.

How to initialize an array with numbers separated by a specific interval in C#

I want to create an array containing values from 0 to 1 with interval of 0.1. I can use:
float[] myArray = new float[10];
float increment = 0.1;
for(i = 0; i < 10; i++)
{
myArray[i] = increment;
increment += 0.1;
}
I was wondering whether there is a function like Enumerable.Range that permits to specify also the increment interval.
An interesting fact is that every answer posted so far has fixed the bug in your proposed code, but only one has called out that they've done so.
Binary floating point numbers have representation error when dealing with any quantity that is not a fraction of an exact power of two. ("3.0/4.0" is a representable fraction because the bottom is a power of two; "1.0/10.0" is not.)
Therefore, when you say:
for(i = 0; i < 10; i++)
{
myArray[i] = increment;
increment += 0.1;
}
You are not actually incrementing "increment" by 1.0/10.0. You are incrementing it by the closest representable fraction that has an exact power of two on the bottom. So in fact this is equivalent to:
for(i = 0; i < 10; i++)
{
myArray[i] = increment;
increment += (exactly_one_tenth + small_representation_error);
}
So, what is the value of the tenth increment? Clearly it is 10 * (exactly_one_tenth + small_representation_error) which is obviously equal to exactly_one + 10 * small_representation_error. You have multiplied the size of the representation error by ten.
Any time you repeatedly add together two floating point numbers, each subsequent addition increases the total representation error of the sum slightly and that adds up, literally, to a potentially large error. In some cases where you are summing thousands or millions of small numbers the error can become far larger than the actual total.
The far better solution is to do what everyone else has done. Recompute the fraction from integers every time. That way each result gets its own small representation error; it does not accumulate the representation errors of previously computed results.
Ugly, but...
Enumerable.Range(0,10).Select(i => i/10.0).ToArray();
No, there's no enumerable range that allows you to do that, but you could always divide by 10:
foreach (int i in Enumerable.Range(0, 10))
array[i] = (i + 1) / 10.0f
Note that this avoids the error that will accumulate if you repeatedly sum 0.1f. For example, if you sum the 10 elements in the myArray in your sample code, you get a value that's closer to 5.50000048 than 5.5.
Here is one way:
Enumerable.Range(1,10).Select(i => i /10.0)
Well you could use this:
Enumerable.Range(1,10).Select(x => x / 10.0).ToArray()
Not sure if that's better though.

Round a number to the next HIGHEST 10

I have a need to create a graph, where the scale of the Y-axis changes depending on the data input into the system. Conceivably this scale could be anywhere from 0-10, 0-100, or even have bottom limit of thousands and an upper limit of millions.
To properly determinethe scale of this axis, I need to work out the ratio of Points to Pixels (based on graph height/range).
Now a graphs' axis never start at the lowest value and go to the highest, usual practice is to go to the next nearest 2, 5 or 10 (above for upper limit, and below for lower) depending on the range of values.
So what I'd like to know is how to take the max value from the data set, and round it up to the nearest 10.
for clarification, the input values will always be integers.
what i have now is this
if ((rangeMax < 10) && (rangeMax > 5))
rangeMax = 10;
else if (rangeMax < 5)
rangeMax = 5;
Which is only useful for values less than 10, and doesn't allow the flexibility required to be truly dynamic. Ultimately this graph will be auto-generated during a page load event, with no user input.
I've read around a bit, and people talk about things like the modulus operator (%), but I can't find any reliable information about it's use, and talk of Math.Ceiling and Math.Round, but these go to the next nearest whole number, which isn't quite there, and don't seem to help much at all when dealing with integers anyway.
Any suggestions, pointers or help greatly appreciated.
i did find a similar question asked here How can i get the next highest multiple of 5 or 10 but i don't know java, so i can't understand any of what was said.
Cheers
if(rangeMax % 10 !=0)
rangeMax = (rangeMax - rangeMax % 10) + 10;
You could also use Math.Round() with MidpointRounding.AwayFromZero using a decimal number (otherwise integer division will truncate fractions):
decimal number = 55M;
decimal nextHighest = Math.Round(number/ 10, MidpointRounding.AwayFromZero) * 10;
If you want to go up to the next 10, you can use Math.Ceiling as follows:
rangeMax = (int)(Math.Ceiling((decimal)rangeMax / 10) * 10);
If you need to generalize to go to the next n (for example 5 here) you can do:
int n = 5;
rangeMax = (int)(Math.Ceiling((decimal)rangeMax / n) * n);
Something which might help is to divide the number by 10. This should round it to the nearest integer. Then multiply it by 10 again to get the number rounded to the nearest 10
I use THIS:
public static double RoundTo10(double number)
{
if (number > 0)
{
return Math.Ceiling(number / 10) * 10;
}
else
{
return Math.Floor(number / 10) * 10;
}
}
you can try this....
decimal val = 95;
//decimal val =Convert.ToDecimal( textBox1.Text);
decimal tmp = 0;
tmp = (val % 10);
//MessageBox.Show(tmp.ToString()+ "Final val:"+(val-tmp).ToString());
decimal finval = val - tmp;

Categories