C#
random decimal
programming
.NET
code example

Generating a random decimal in C

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

C# provides several ways to generate random decimal numbers. Random.NextDouble() returns a double between 0.0 and 1.0, which you can scale to any range. For the decimal type specifically (needed in financial calculations), there is no built-in NextDecimal() method, so you build one from random bytes or by combining random integers. For cryptographically secure random numbers, use RandomNumberGenerator instead of System.Random.

Random Double (0.0 to 1.0)

csharp
1var random = new Random();
2
3// Returns a double >= 0.0 and < 1.0
4double value = random.NextDouble();
5Console.WriteLine(value); // e.g., 0.7345812...

Random Double in a Custom Range

csharp
1var random = new Random();
2
3// Random double between min and max
4double RandomInRange(double min, double max)
5{
6    return min + (random.NextDouble() * (max - min));
7}
8
9double price = RandomInRange(9.99, 49.99);
10Console.WriteLine($"Price: {price:F2}"); // e.g., Price: 27.43
11
12double temperature = RandomInRange(-20.0, 45.0);
13Console.WriteLine($"Temp: {temperature:F1}°C"); // e.g., Temp: 12.3°C

The formula min + (NextDouble() * (max - min)) generates a uniform random value in [min, max).

Random Float

csharp
1var random = new Random();
2
3// .NET 6+ has Random.NextSingle()
4float value = random.NextSingle(); // 0.0f to 1.0f
5
6// For older .NET versions, cast from double
7float value2 = (float)random.NextDouble();
8
9// Float in range
10float RandomFloat(float min, float max)
11{
12    return min + (random.NextSingle() * (max - min));
13}

Random Decimal

System.Random has no NextDecimal() method. Build one from random components:

Method 1: Scale from Double

csharp
1var random = new Random();
2
3// Simple but limited to double's 15-16 digit precision
4decimal RandomDecimal(decimal min, decimal max)
5{
6    double range = (double)(max - min);
7    return min + (decimal)(random.NextDouble() * range);
8}
9
10decimal amount = RandomDecimal(0.01m, 999.99m);
11Console.WriteLine($"Amount: {amount:C}"); // e.g., Amount: $542.17

Method 2: From Random Bytes (Full Precision)

csharp
1decimal NextDecimal(Random random)
2{
3    // decimal has 96-bit integer + scale (0-28) + sign
4    int lo = random.Next();
5    int mid = random.Next();
6    int hi = random.Next();
7    bool isNegative = random.Next(2) == 1;
8    byte scale = (byte)random.Next(29); // 0 to 28
9
10    return new decimal(lo, mid, hi, isNegative, scale);
11}
12
13var random = new Random();
14decimal d = NextDecimal(random);
15Console.WriteLine(d);

Method 3: Decimal in Range with Precision

csharp
1decimal RandomDecimalInRange(Random random, decimal min, decimal max, int decimalPlaces = 2)
2{
3    double range = (double)(max - min);
4    decimal value = min + (decimal)(random.NextDouble() * range);
5    return Math.Round(value, decimalPlaces);
6}
7
8var random = new Random();
9decimal price = RandomDecimalInRange(random, 1.00m, 100.00m, 2);
10Console.WriteLine($"${price}"); // e.g., $47.83

Cryptographically Secure Random

System.Random is a pseudorandom number generator (PRNG) — predictable given the seed. For security-sensitive applications, use RandomNumberGenerator:

csharp
1using System.Security.Cryptography;
2
3// .NET 6+ simplified API
4double secureDouble = RandomNumberGenerator.GetInt32(int.MaxValue) / (double)int.MaxValue;
5
6// Full method for secure random double
7double SecureRandomDouble()
8{
9    byte[] bytes = new byte[8];
10    RandomNumberGenerator.Fill(bytes);
11    ulong value = BitConverter.ToUInt64(bytes, 0);
12    return (double)value / ulong.MaxValue;
13}
14
15double secureValue = SecureRandomDouble();
16Console.WriteLine(secureValue);
csharp
1// Secure random in range
2double SecureRandomInRange(double min, double max)
3{
4    return min + SecureRandomDouble() * (max - min);
5}

Thread Safety

System.Random is not thread-safe. In multi-threaded code:

csharp
1// WRONG — shared Random instance causes duplicate values or exceptions
2static Random shared = new Random();
3
4// Option 1: .NET 6+ shared thread-safe instance
5double value = Random.Shared.NextDouble();
6
7// Option 2: ThreadLocal for older .NET
8static readonly ThreadLocal<Random> threadRandom =
9    new(() => new Random(Guid.NewGuid().GetHashCode()));
10
11double threadSafeValue = threadRandom.Value.NextDouble();
12
13// Option 3: Lock (slower)
14static readonly Random lockedRandom = new Random();
15static readonly object lockObj = new();
16
17double LockedNextDouble()
18{
19    lock (lockObj) { return lockedRandom.NextDouble(); }
20}

Generating Random Decimal Arrays

csharp
1var random = new Random();
2
3// Array of random doubles
4double[] prices = Enumerable.Range(0, 100)
5    .Select(_ => Math.Round(random.NextDouble() * 100, 2))
6    .ToArray();
7
8// Array of random decimals in a range
9decimal[] amounts = Enumerable.Range(0, 50)
10    .Select(_ => Math.Round((decimal)(random.NextDouble() * 1000), 2))
11    .ToArray();

Common Pitfalls

  • Creating new Random() instances in a tight loop: new Random() seeds from the system clock. Multiple instances created within the same millisecond produce identical sequences. Use a single instance or Random.Shared (.NET 6+).
  • Assuming NextDouble() can return 1.0: NextDouble() returns values in [0.0, 1.0) — the upper bound is exclusive. The maximum value is 0.99999999999999978. If you need an inclusive upper bound, add a small epsilon to the range.
  • Using Random for security-sensitive purposes: System.Random is predictable if the seed is known. Use RandomNumberGenerator from System.Security.Cryptography for tokens, passwords, or any security-related randomness.
  • Casting decimal to double for range calculation: The decimal type has higher precision (28-29 significant digits) than double (15-16 digits). Casting to double for intermediate calculations loses precision. For financial applications, use integer-based approaches.
  • Sharing Random across threads without synchronization: System.Random is not thread-safe. Concurrent access can corrupt internal state, producing all zeros or throwing exceptions. Use Random.Shared, ThreadLocal<Random>, or locking.

Summary

  • Use random.NextDouble() for a random double in [0.0, 1.0), scale with min + NextDouble() * (max - min) for custom ranges
  • Use random.NextSingle() (.NET 6+) for random floats
  • Build NextDecimal() from random integers or scale from NextDouble() for the decimal type
  • Use RandomNumberGenerator for cryptographically secure random numbers
  • Use Random.Shared (.NET 6+) or ThreadLocal<Random> for thread-safe random generation

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.