Generating a Random Decimal in C#

Generating a Random Decimal in C#

EDIT: Removed old version

This is similar to Daniel's version, but will give the complete range. It also introduces a new extension method to get a random "any integer" value, which I think is handy.

Note that the distribution of decimals here is not uniform.

/// <summary>
/// Returns an Int32 with a random value across the entire range of
/// possible values.
/// </summary>
public static int NextInt32(this Random rng)
{
int firstBits = rng.Next(0, 1 << 4) << 28;
int lastBits = rng.Next(0, 1 << 28);
return firstBits | lastBits;
}

public static decimal NextDecimal(this Random rng)
{
byte scale = (byte) rng.Next(29);
bool sign = rng.Next(2) == 1;
return new decimal(rng.NextInt32(),
rng.NextInt32(),
rng.NextInt32(),
sign,
scale);
}

C# Generating Random Decimals between Two Decimals

y=mx+c. Generate a 0<=X<1 FP random with NextDouble(), multiply it up by (Dmax-Dmin) into the right range, then add Dmin to shift the base.

Random numbers with decimals

use NextDouble:

 rnd.NextDouble() * (23.5-18.0) + 18.0

or more generically:

public double NextDouble(Random rnd, double min, double max)
{
return rnd.NextDouble() * (max-min) + min;
}

Random float in C#

 var rand = new Random(); 
var rndNumber = new decimal(rand.NextDouble());
rndNumber = rndNumber * 6 - 3;

NextDouble() returns a double between 0 and 1 multiply this by the range you want 6 then shift it by the offset you.want -3

Generate random number between 1 and 3 / including 1 decimal place

You can multiply the result like this:

float result = rnd.Next(10, 31) * .1f;

This will result in a range from 1.0 to 3.0, stepping by .1.

How to show a random number to 2 decimal places

To generate a number with decimal places you should use NextDouble()method.

Random r = new Random();
double egg = r.NextDouble();
Console.WriteLine(String.Format("price {0}", egg.ToString("n2")));

How to generate a random double number in the inclusive [0,1] range?

After taking a shower, I have conceived of a potential solution based on my understanding of how a random floating point generator works. My solution makes three assumptions, which I believe to be reasonable, however I can not verify if these assumptions are correct or not. Because of this, the following code is purely academic in nature, and I would not recommend its use in practice. The assumptions are as follows:

  1. The distribution of random.NextDouble() is uniform
  2. The difference between any two adjacent numbers in the range produced by random.NextDouble() is a constant epsilon e
  3. The maximum value generated by random.NextDouble() is equal to 1 - e

Provided that those three assumptions are correct, the following code generates random doubles in the range [0, 1].

// For the sake of brevity, we'll omit the finer details of reusing a single instance of Random
var random = new Random();

double RandomDoubleInclusive() {
double d = 0.0;
int i = 0;

do {
d = random.NextDouble();
i = random.Next(2);
} while (i == 1 && d > 0)

return d + i;
}

This is somewhat difficult to conceptualize, but the essence is somewhat like the below coin-flipping explanation, except instead of a starting value of 0.5, you start at 1, and if at any point the sum exceeds 1, you restart the entire process.

From an engineering standpoint, this code is a blatant pessimization with little practical advantage. However, mathematically, provided that the original assumptions are correct, the result will be as mathematically sound as the original implementation.

Below is the original commentary on the nature of random floating point values and how they're generated.

Original Reply:

Your question carries with it a single critical erroneous assumption: Your use of the word "Correct". We are working with floating point numbers. We abandoned correctness long ago.

What follows is my crude understanding of how a random number generator produces a random floating point value.

You have a coin, a sum starting at zero, and a value starting at one half (0.5).

  1. Flip the coin.
  2. If heads, add the value to the sum.
  3. Half the value.
  4. Repeat 23 times.

You have just generated a random number. Here are some properties of the number (for reference, 2^23 is 8,388,608, and 2^(-23) is the inverse of that, or approximately 0.0000001192):

  • The number is one of 2^23 possible values
  • The lowest value is 0
  • The highest value is 1 - 2^(-23);
  • The smallest difference between any two potential values is 2^(-23)
  • The values are evenly distributed across the range of potential values
  • The odds of getting any one value are completely uniform across the range
  • Those last two points are true regardless of how many times you flip the coin
  • The process for generating the number was really really easy

That last point is the kicker. It means if you can generate raw entropy (i.e. perfectly uniform random bits), you can generate an arbitrarily precise number in a very useful range with complete uniformity. Those are fantastic properties to have. The only caveat is that it doesn't generate the number 1.

The reason that caveat is seen as acceptable is because every other aspect of the generation is so damned good. If you're trying to get a high precision random value between 0 and 1, chances are you don't actually care about landing on 1 any more than you care about landing on 0.38719, or any other random number in that range.

While there are methods for getting 1 included in your range (which others have stated already), they're all going to cost you in either speed or uniformity. I'm just here to tell you that it might not actually be worth the tradeoff.

How do I generate random number between 0 and 1 in C#?

According to the documentation, Next returns an integer random number between the (inclusive) minimum and the (exclusive) maximum:

Return Value

A 32-bit signed integer greater than or equal to minValue and less than maxValue; that is, the range of return values includes minValue but not maxValue. If minValue equals maxValue, minValue is returned.

The only integer number which fulfills

0 <= x < 1

is 0, hence you always get the value 0. In other words, 0 is the only integer that is within the half-closed interval [0, 1).

So, if you are actually interested in the integer values 0 or 1, then use 2 as upper bound:

var n = random.Next(0, 2);

If instead you want to get a decimal between 0 and 1, try:

var n = random.NextDouble();

C#: Round decimals for var made of Random

If you take your variable decreturn and do Math.Round(decreturn, 2) or String.Format("{0:F2}", decreturn), it works as expected.

The following example is working:

using System;

public class Program
{
public static void Main()
{
Random RNG = new Random();
decimal divab50 = RNG.Next(50,100);
decimal divbl50 = RNG.Next(6,50);
decimal decreturn = divab50 / divbl50;
decimal rounded = Math.Round(decreturn, 2);
Console.WriteLine(rounded);
}
}

Fiddle to test with Math.Round: https://dotnetfiddle.net/70LTrm

You could also apply String.Format for this purpose like this:

using System;

public class Program
{
public static void Main()
{
Random RNG = new Random();
decimal divab50 = RNG.Next(50,100);
decimal divbl50 = RNG.Next(6,50);
decimal decreturn = divab50 / divbl50;
var rounded = String.Format("{0:F2}", decreturn);
Console.WriteLine(rounded);
}
}

Fiddle to test with String.Format: https://dotnetfiddle.net/6Yy8uU

Take a look to the documentation of Math.Round and String.Format for more info.



Related Topics



Leave a reply



Submit