Willekeurig getal tussen 2 dubbele getallen

Is het mogelijk om een ​​willekeurig getal tussen 2 dubbels te genereren?

Voorbeeld:

public double GetRandomeNumber(double minimum, double maximum)
{
    return Random.NextDouble(minimum, maximum) 
}

Dan noem ik het met het volgende:

double result = GetRandomNumber(1.23, 5.34);

Alle gedachten worden op prijs gesteld.


Antwoord 1, autoriteit 100%

Ja.

Random.NextDouble retourneert een double tussen 0 en 1. Je vermenigvuldigt dat vervolgens met het bereik waar je in moet gaan (verschil tussen maximum en minimum) en voegt dat toe aan de basis (minimum).

public double GetRandomNumber(double minimum, double maximum)
{ 
    Random random = new Random();
    return random.NextDouble() * (maximum - minimum) + minimum;
}

Echte code zou willekeurig een statisch lid moeten zijn. Dit bespaart u de kosten voor het maken van de generator voor willekeurige getallen en stelt u in staat om GetRandomNumber heel vaak te bellen. Aangezien we bij elke oproep een nieuwe RNG initialiseren, wordt de RNG, als u snel genoeg belt zodat de systeemtijd niet verandert tussen oproepen, geplaatst met exact dezelfde tijdstempel en dezelfde stroom willekeurige getallen gegenereerd.


Antwoord 2, autoriteit 12%

Johnny5 stelde voor om een ​​extensiemethode te maken. Hier is een vollediger codevoorbeeld dat laat zien hoe u dit zou kunnen doen:

public static class RandomExtensions
{
    public static double NextDouble(
        this Random random,
        double minValue,
        double maxValue)
    {
        return random.NextDouble() * (maxValue - minValue) + minValue;
    }
}

Je kunt het nu aanroepen alsof het een methode is in de klasse Random:

Random random = new Random();
double value = random.NextDouble(1.23, 5.34);

Houd er rekening mee dat u niet veel nieuwe Randomobjecten in een lus moet maken, omdat dit de kans vergroot dat u dezelfde waarde vele malen achter elkaar krijgt. Als je veel willekeurige getallen nodig hebt, maak dan één instantie van Randomen hergebruik deze.


Antwoord 3, autoriteit 3%

Pas op: als u de Randomgenereert in een lus zoals bijvoorbeeld for(int i = 0; i < 10; i++), doe dat dan niet plaats de new Random()-declaratie in de lus.

Van MSDN:

Het genereren van willekeurige getallen begint met een startwaarde. Als hetzelfde
seed herhaaldelijk wordt gebruikt, wordt dezelfde reeks getallen gegenereerd. Een
manier om verschillende reeksen te produceren, is door de startwaarde te maken
tijdsafhankelijk, waardoor er bij elke nieuwe . een andere serie ontstaat
exemplaar van Random. Standaard is de parameterloze constructor van de
Willekeurige klasse gebruikt de systeemklok om zijn startwaarde te genereren…

Dus op basis van dit feit, doe iets als:

var random = new Random();
for(int d = 0; d < 7; d++)
{
    // Actual BOE
    boes.Add(new LogBOEViewModel()
    {
        LogDate = criteriaDate,
        BOEActual = GetRandomDouble(random, 100, 1000),
        BOEForecast = GetRandomDouble(random, 100, 1000)
    });
}
double GetRandomDouble(Random random, double min, double max)
{
     return min + (random.NextDouble() * (max - min));
}

Op deze manier heb je de garantie dat je verschillende dubbele waarden krijgt.


Antwoord 4, autoriteit 2%

Ik ben een beetje laat op het feest, maar ik moest een algemene oplossing implementeren en het bleek dat geen van de oplossingen aan mijn behoeften kon voldoen.

De geaccepteerde oplossing is goed voor kleine reeksen; maximum - minimumkan echter oneindig zijn voor grote bereiken. Een gecorrigeerde versie kan dus deze versie zijn:

public static double NextDoubleLinear(this Random random, double minValue, double maxValue)
{
    // TODO: some validation here...
    double sample = random.NextDouble();
    return (maxValue * sample) + (minValue * (1d - sample));
}

Dit genereert mooie willekeurige getallen, zelfs tussen double.MinValueen Double.MaxValue. Maar dit introduceert een ander “probleem”, dat mooi wordt gepresenteerd in dit bericht: als we zulke grote bereiken gebruiken, lijken de waarden misschien te “onnatuurlijk”. Bijvoorbeeld, na het genereren van 10.000 willekeurige verdubbelingen tussen 0 en Double.MaxValuelagen alle waarden tussen 2,9579E+304 en 1,7976E+308.

Dus ik heb ook een andere versie gemaakt, die getallen genereert op een logaritmische schaal:

public static double NextDoubleLogarithmic(this Random random, double minValue, double maxValue)
{
    // TODO: some validation here...
    bool posAndNeg = minValue < 0d && maxValue > 0d;
    double minAbs = Math.Min(Math.Abs(minValue), Math.Abs(maxValue));
    double maxAbs = Math.Max(Math.Abs(minValue), Math.Abs(maxValue));
    int sign;
    if (!posAndNeg)
        sign = minValue < 0d ? -1 : 1;
    else
    {
        // if both negative and positive results are expected we select the sign based on the size of the ranges
        double sample = random.NextDouble();
        var rate = minAbs / maxAbs;
        var absMinValue = Math.Abs(minValue);
        bool isNeg = absMinValue <= maxValue ? rate / 2d > sample : rate / 2d < sample;
        sign = isNeg ? -1 : 1;
        // now adjusting the limits for 0..[selected range]
        minAbs = 0d;
        maxAbs = isNeg ? absMinValue : Math.Abs(maxValue);
    }
    // Possible double exponents are -1022..1023 but we don't generate too small exponents for big ranges because
    // that would cause too many almost zero results, which are much smaller than the original NextDouble values.
    double minExponent = minAbs == 0d ? -16d : Math.Log(minAbs, 2d);
    double maxExponent = Math.Log(maxAbs, 2d);
    if (minExponent == maxExponent)
        return minValue;
    // We decrease exponents only if the given range is already small. Even lower than -1022 is no problem, the result may be 0
    if (maxExponent < minExponent)
        minExponent = maxExponent - 4;
    double result = sign * Math.Pow(2d, NextDoubleLinear(random, minExponent, maxExponent));
    // protecting ourselves against inaccurate calculations; however, in practice result is always in range.
    return result < minValue ? minValue : (result > maxValue ? maxValue : result);
}

Enkele tests:

Hier zijn de gesorteerde resultaten van het genereren van 10.000 willekeurige dubbele getallen tussen 0 en Double.MaxValuemet beide strategieën. De resultaten worden weergegeven met een logaritmische schaal:

Hoewel de lineaire willekeurige waarden op het eerste gezicht verkeerd lijken, laten de statistieken zien dat geen van hen “beter” is dan de andere: zelfs de lineaire strategie heeft een gelijkmatige verdeling en het gemiddelde verschil tussen de waarden is vrijwel hetzelfde met beide strategieën.

Spelen met verschillende reeksen leerde me dat de lineaire strategie “sane” wordt met een bereik tussen 0 en ushort.MaxValuemet een “redelijke” minimumwaarde van 10.78294704
(voor ulongbereik was de minimumwaarde 3.03518E+15; int: 353341). Dit zijn dezelfde resultaten van beide strategieën weergegeven met verschillende schalen:


Bewerken:

Onlangs heb ik mijn bibliotheken open source, voel vrij om de RandomExtensions.NextDoubleMethode met de volledige validatie.


Antwoord 5, Autoriteit 2%

De eenvoudigste aanpak zou eenvoudigweg een willekeurig aantal genereren tussen 0 en het verschil van de twee nummers. Voeg vervolgens de kleinere van de twee nummers toe aan het resultaat.


Antwoord 6

U kunt code als volgt gebruiken:

public double getRandomNumber(double minimum, double maximum) {
    return minimum + randomizer.nextDouble() * (maximum - minimum);
}

Antwoord 7

U kunt dit doen:

public class RandomNumbers : Random
{
    public RandomNumbers(int seed) : base(seed) { }
    public double NextDouble(double minimum, double maximum)
    {
        return base.NextDouble() * (maximum - minimum) + minimum;
    }
}

Antwoord 8

Wat als een van de waarden negatief is? Zou geen beter idee zijn:

double NextDouble(double min, double max)
{
       if (min >= max)
            throw new ArgumentOutOfRangeException();    
       return random.NextDouble() * (Math.Abs(max-min)) + min;
}

Antwoord 9

Over het genereren van hetzelfde willekeurig nummer als u het in een lus noemt, is een handige oplossing om het nieuwe willekeurige () object buiten de lus als een globale variabele te verklaren.

Merk op dat u uw exemplaar van de willekeurige klasse buiten de GetRandomint-functie moet declareren als u dit in een lus gaat gebruiken.

“Waarom is dit?” je vraagt.

Nou, de willekeurige klasse genereert eigenlijk pseudo-willekeurige nummers, met het “zaad” voor de randomizer als de systeemtijd. Als uw lus voldoende snel is, verschijnt de kloktijd van het systeem niet anders dan de randomizer en zou elk nieuw exemplaar van de willekeurige klasse beginnen met hetzelfde zaad en geef u hetzelfde pseudo-willekeurig nummer.

Bron is hier: http://www.wypad.com/posts/csharp-get-a-random-number-between-x-and-y/412/


Antwoord 10

Random random = new Random();
double NextDouble(double minimum, double maximum)
{  
    return random.NextDouble()*random.Next(minimum,maximum);
}

Antwoord 11

Als u een willekeurig getal in het bereik nodig hebt [double.MinValue; double.MaxValue]

// Because of:
double.MaxValue - double.MinValue == double.PositiveInfinity
// This will be equals to NaN or PositiveInfinity
random.NextDouble() * (double.MaxValue - double.MinValue)

Gebruik in plaats daarvan:

public static class RandomExtensions
{
    public static double NextDoubleInMinMaxRange(this Random random)
    {
        var bytes = new byte[sizeof(double)];
        var value = default(double);
        while (true)
        {
            random.NextBytes(bytes);
            value = BitConverter.ToDouble(bytes, 0);
            if (!double.IsNaN(value) && !double.IsInfinity(value))
                return value;
        }
    }
}

Antwoord 12

Gebruik een statische willekeurige of de cijfers die de neiging hebben om in strakke / snelle lussen te herhalen vanwege de systeemklok die ze zaait.

public static class RandomNumbers
{
    private static Random random = new Random();
    //=-------------------------------------------------------------------
    // double between min and the max number
    public static double RandomDouble(int min, int max) 
    {
        return (random.NextDouble() * (max - min)) + min;
    }
    //=----------------------------------
    // double between 0 and the max number
    public static double RandomDouble(int max) 
    {
        return (random.NextDouble() * max);
    }
    //=-------------------------------------------------------------------
    // int between the min and the max number
    public static int RandomInt(int min, int max) 
    {   
        return random.Next(min, max + 1);
    }
    //=----------------------------------
    // int between 0 and the max number
    public static int RandomInt(int max) 
    {
        return random.Next(max + 1);
    }
    //=-------------------------------------------------------------------
 }

Zie ook: https:// docs.microsoft.com/en-us/dotnet/api/system.random?view=netframework-4.8

Other episodes