mercredi 27 novembre 2019

Calculate number of distinct values between two numbers at a given precision

Context: I am building a random-number generating user interface where a user can enter values for the following:

  • lowerLimit: the lower limit for each randomly generated number
  • upperLimit: the upper limit for each randomly generated number
  • maxPrecision: the maximum precision each randomly generated number
  • Quantity: the maximum number of random number values to be generated

The question is: how can I ensure that at a given lowerLimit/upperLimit range and at a given precision, that the user does not request a greater quantity than is possible?

Example:

lowerLimit: 1 upperLimit: 1.01 maxPrecision: 3 Quantity: 50

At this precision level (3), there are 11 possible values between 1 and 1.01: 1.000, 1.001, 1.002, 1.003, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.100, yet the user is asking for the top 50.

In one version of the function that returns only distinct values that match user criteria, I am using a dictionary object to store already-generated values and if the value already exists, try another random number until I have found X distinct random number values where X is the user-desired quantity. The problem is, my logic allows for a never-ending loop if the number of possible values is less than the user-entered quantity.

While I could probably employ logic to detect runaway condition, I thought it would be a nicer approach to somehow calculate the quantity of possible return values in advance to make sure it is possible. But that logic is eluding me. (Haven't tried anything because I can't think of how to do it).

private Random RandomSeed = new Random();
public double GetRandomDouble(double lowerBounds, double upperBounds, int maxPrecision)
{
    //Return a randomly-generated double between lowerBounds and upperBounds 
    //with maximum precision of maxPrecision
    double x = (RandomSeed.NextDouble() * ((upperBounds - lowerBounds))) + lowerBounds;
    return Math.Round(x, maxPrecision);
}
public double[] GetRandomDoublesUnique(double lowerBounds, double upperBounds, int maxPrecision, int quantity)
{
    //This method returns an array of doubles containing randomly-generated numbers
    //between user-entered lowerBounds and upperBounds with a maximum precision of
    //maxPrecision.  The array size is capped at user-entered quantity.

    //Create Dictionary to store number values already generated so we can ensure
    //we don't have duplicates
    Dictionary<double, int> myDoubles = new Dictionary<double, int>();
    double[] returnValues = new double[quantity];
    double nextValue;
    for (int i = 0; i < quantity; i++)
    {
        nextValue = GetRandomDouble(lowerBounds, upperBounds, maxPrecision);
        if (!myDoubles.ContainsKey(nextValue))
        {
            myDoubles.Add(nextValue, i);
            returnValues[i] = nextValue;
        }
        else
        {
            i -= 1;
        }
    }
    return returnValues;
}



Aucun commentaire:

Enregistrer un commentaire