/// <summary> /// A random <see cref="double"/> between <paramref name="minValue"/> (inclusive) and <paramref name="maxValue"/> /// (inclusive). If you wish to have an exclusive range, /// use <see cref="MathExtensions.NextAfter(float, double)"/> to adjust the range. /// <para/> /// The code was inspired by GeoTestUtil from Apache Lucene. /// </summary> /// <param name="random">The <see cref="Random"/> instance.</param> /// <param name="minValue">Left range boundary, inclusive. May be <see cref="double.NegativeInfinity"/>, but not <see cref="double.NaN"/>.</param> /// <param name="maxValue">Right range boundary, inclusive. May be <see cref="double.PositiveInfinity"/>, but not <see cref="double.NaN"/>.</param> /// <returns>A random <see cref="double"/> between <paramref name="minValue"/> (inclusive) and <paramref name="maxValue"/> /// (inclusive).</returns> /// <exception cref="ArgumentException"><paramref name="minValue"/> is greater than <paramref name="maxValue"/>.</exception> /// <exception cref="ArgumentOutOfRangeException"><paramref name="minValue"/> or <paramref name="maxValue"/> is <see cref="double.NaN"/>.</exception> /// <exception cref="ArgumentNullException"><paramref name="random"/> is <c>null</c>.</exception> public static double RandomDoubleBetween(Random random, double minValue, double maxValue) { if (random is null) { throw new ArgumentNullException(nameof(random)); } if (maxValue < minValue) { throw new ArgumentException($"{nameof(minValue)} must be greater than or equal to {nameof(maxValue)}: {minValue}, {maxValue}"); } if (double.IsNaN(minValue)) { throw new ArgumentOutOfRangeException(nameof(minValue), $"{nameof(minValue)} must not be {nameof(double.NaN)}"); } if (double.IsNaN(maxValue)) { throw new ArgumentOutOfRangeException(nameof(maxValue), $"{nameof(maxValue)} must not be {nameof(double.NaN)}"); } bool hasZero = minValue <= 0 && maxValue >= 0; int pick = random.Next( EvilRangeLeft + EvilRangeRight + EvilVeryCloseRangeEnds + (hasZero ? EvilZeroOrNear : 0) + EvilSimpleProportion + EvilRandomRepresentationBits); // Exact range ends pick -= EvilRangeLeft; if (pick < 0 || minValue == maxValue) { return(minValue); } pick -= EvilRangeRight; if (pick < 0) { return(maxValue); } // If we're dealing with infinities, adjust them to discrete values. Debug.Assert(minValue != maxValue); if (double.IsInfinity(minValue)) { minValue = minValue.NextUp(); } if (double.IsInfinity(maxValue)) { maxValue = maxValue.NextAfter(double.NegativeInfinity); } // Numbers "very" close to range ends. "very" means a few floating point // representation steps (ulps) away. pick -= EvilVeryCloseRangeEnds; if (pick < 0) { if (random.NextBoolean()) { return(FuzzUp(random, minValue, maxValue)); } else { return(FuzzDown(random, maxValue, minValue)); } } // Zero or near-zero values, if within the range. if (hasZero) { pick -= EvilZeroOrNear; if (pick < 0) { int v = random.Next(4); if (v == 0) { return(0d); } else if (v == 1) { return(-0.0d); } else if (v == 2) { return(FuzzDown(random, 0d, minValue)); } else if (v == 3) { return(FuzzUp(random, 0d, maxValue)); } } } // Simple proportional selection. pick -= EvilSimpleProportion; if (pick < 0) { return(minValue + (maxValue - minValue) * random.NextDouble()); } // Random representation space selection. This will be heavily biased // and overselect from the set of tiny values, if they're allowed. pick -= EvilRandomRepresentationBits; if (pick < 0) { long from = ToSortable(minValue); long to = ToSortable(maxValue); return(FromSortable(RandomNumbers.RandomInt64Between(random, from, to))); } throw new Exception("Unreachable."); }
public static long NextInt64(Random random, long minValue, long maxValue) { return(RandomInts.RandomInt64Between(random, minValue, maxValue)); // LUCENENET: Moved general random data generation to RandomizedTesting.Generators }
/** * A random long from <code>min</code> to <code>max</code> (inclusive). */ public static long RandomInt64Between(long min, long max) { return(RandomNumbers.RandomInt64Between(Random, min, max)); }