2 डबल संख्याओं के बीच यादृच्छिक संख्या


156

क्या 2 डबल्स के बीच एक यादृच्छिक संख्या उत्पन्न करना संभव है?

उदाहरण:

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

तो मैं इसे निम्नलिखित के साथ कहता हूं:

double result = GetRandomNumber(1.23, 5.34);

किसी भी विचार की सराहना की जाएगी।

जवाबों:


329

हाँ।

Random.NextDouble 0 और 1. के बीच एक डबल देता है। फिर आप उस सीमा से गुणा करते हैं जिसमें आपको अधिकतम (न्यूनतम और न्यूनतम के बीच का अंतर) में जाना होता है और फिर उसे आधार (न्यूनतम) में जोड़ते हैं।

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

वास्तविक कोड में यादृच्छिक एक स्थिर सदस्य होना चाहिए। यह यादृच्छिक संख्या जनरेटर बनाने की लागत को बचाएगा, और आपको GetRandomNumber को बहुत बार कॉल करने में सक्षम करेगा। चूंकि हम हर कॉल के साथ एक नए RNG को इनिशियलाइज़ कर रहे हैं, अगर आप इतनी जल्दी कॉल करते हैं कि RNG कॉल के बीच का सिस्टम टाइम नहीं बदलता है तो वही टाइमस्टैम्प के साथ सीड हो जाएगा, और रैंडम नंबर की समान स्ट्रीम जेनरेट करेगा।


33
बस देखो अगर तुम एक पाश में GetRandomNumber () कहते हैं, क्योंकि यह अधिक से अधिक मूल्य पैदा करेगा
जॉन रस

13
एक अच्छा public double GetRandomNumber(this Random random, double minimum, double maximum) {...}
निकालने की

5
ध्यान रखें कि चूंकि random.NextDouble कभी भी 1.0 नहीं लौटाता है, इसलिए यह फ़ंक्शन भी अधिकतम संख्या के बराबर नहीं होगा।
मैथ्यू

6
मैं एक बीज नए रैंडम ((int) DateTime.Now.Ticks) के रूप में डालने का सुझाव देता हूं, इसे त्वरित छोरों में भी इसे "अधिक यादृच्छिक" बनाना चाहिए।
डैनियल स्काउरोस्की

5
यह काम नहीं करता है यदि न्यूनतम मान डबल है। वैल्यू और अधिकतम मूल्य डबल है। मैक्सवेल। इस उपयोग के मामले को संभालने के बारे में कोई सुझाव?
जीन एस

40

जॉनी 5 ने एक विस्तार विधि बनाने का सुझाव दिया। यहां एक और पूर्ण कोड उदाहरण दिखाया गया है कि आप यह कैसे कर सकते हैं:

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

अब आप इसे कॉल कर सकते हैं जैसे कि यह Randomकक्षा पर एक विधि थी :

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

ध्यान दें कि आपको Randomएक लूप में बहुत सी नई वस्तुएं नहीं बनानी चाहिए क्योंकि इससे यह संभावना होगी कि आपको एक पंक्ति में कई बार समान मूल्य मिलें। यदि आपको बहुत सारे यादृच्छिक संख्याओं की आवश्यकता है, तो इसका एक उदाहरण बनाएं Randomऔर इसे फिर से उपयोग करें।


9

बाहर देखें: यदि आप randomउदाहरण के लिए एक लूप के अंदर पैदा कर रहे हैं for(int i = 0; i < 10; i++), तो new Random()घोषणा को लूप के अंदर न डालें ।

से MSDN :

यादृच्छिक संख्या पीढ़ी बीज मूल्य से शुरू होती है। यदि एक ही बीज का बार-बार उपयोग किया जाता है, तो संख्याओं की समान श्रृंखला उत्पन्न होती है। अलग-अलग अनुक्रमों का उत्पादन करने का एक तरीका बीज मूल्य समय-निर्भर बनाना है, जिससे रैंडम के प्रत्येक नए उदाहरण के साथ एक अलग श्रृंखला का उत्पादन किया जाता है। डिफ़ॉल्ट रूप से, रैंडम वर्ग का पैरामीटर रहित कंस्ट्रक्टर सिस्टम बीज का उपयोग इसके बीज मान को उत्पन्न करने के लिए करता है ...

तो इस तथ्य के आधार पर, कुछ इस प्रकार करें:

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));
}

इस तरह से आपके पास गारंटी है कि आपको अलग-अलग दोहरे मान मिलेंगे।


8

सबसे सरल दृष्टिकोण केवल 0 और दो संख्याओं के अंतर के बीच एक यादृच्छिक संख्या उत्पन्न करेगा। फिर परिणाम में दो संख्याओं में से छोटा जोड़ दें।


3

आप इस तरह कोड का उपयोग कर सकते हैं:

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

2

आप ऐसा कर सकते हैं:

public class RandomNumbers : Random
{
    public RandomNumbers(int seed) : base(seed) { }

    public double NextDouble(double minimum, double maximum)
    {
        return base.NextDouble() * (maximum - minimum) + minimum;
    }
}

2

मुझे पार्टी में थोड़ी देर हो गई है लेकिन मुझे एक सामान्य समाधान को लागू करने की आवश्यकता है और यह पता चला है कि कोई भी समाधान मेरी जरूरतों को पूरा नहीं कर सकता है।

स्वीकृत समाधान छोटी श्रेणियों के लिए अच्छा है; हालाँकि, maximum - minimumबड़ी रेंज के लिए अनंत हो सकता है। तो एक सही संस्करण यह संस्करण हो सकता है:

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));
}

यह भी double.MinValueऔर के बीच अच्छी तरह से यादृच्छिक संख्या उत्पन्न करता है double.MaxValue। लेकिन यह एक और "समस्या" का परिचय देता है, जो इस पोस्ट में अच्छी तरह से प्रस्तुत किया गया है : यदि हम ऐसी बड़ी श्रेणियों का उपयोग करते हैं तो मान भी "अनावश्यक" लग सकते हैं। उदाहरण के लिए, 0 के बीच 10,000 यादृच्छिक युगल उत्पन्न करने के बाद और double.MaxValueसभी मान 2.9579E + 304 और 1.7976E + 308 के बीच थे।

इसलिए मैंने एक और संस्करण भी बनाया, जो एक लघुगणकीय पैमाने पर संख्या उत्पन्न करता है:

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);
}

कुछ परीक्षण:

यहाँ 0 और Double.MaxValueदोनों रणनीतियों के साथ 10,000 यादृच्छिक डबल नंबर उत्पन्न करने के लिए हल किए गए परिणाम हैं । परिणाम लघुगणकीय पैमाने का उपयोग करके प्रदर्शित किए जाते हैं:

0..Double.MaxValue

यद्यपि पहली नज़र में रेखीय यादृच्छिक मान गलत प्रतीत होते हैं, लेकिन आंकड़े बताते हैं कि उनमें से कोई भी अन्य की तुलना में "बेहतर" नहीं है: यहां तक ​​कि रैखिक रणनीति का भी समान वितरण है और मूल्यों के बीच औसत अंतर दोनों रणनीतियों के साथ बहुत समान हैं ।

विभिन्न श्रेणियों के साथ खेलने से मुझे पता चला कि रैखिक रणनीति 0 के बीच की सीमा के साथ "समझदार" हो जाती है और ushort.MaxValue10.78294704 के "उचित" न्यूनतम मूल्य के साथ ( ulongन्यूनतम मूल्य 3.03518E + 15 के लिए होता है ; int: 353341)। ये अलग-अलग पैमानों के साथ प्रदर्शित दोनों रणनीतियों के समान परिणाम हैं:

0..UInt16.MaxValue


संपादित करें:

हाल ही में मैंने अपने पुस्तकालयों को खुला स्रोत बनाया , RandomExtensions.NextDoubleपूरी मान्यता के साथ विधि को देखने के लिए स्वतंत्र महसूस करें ।


1

यदि मूल्यों में से एक नकारात्मक है तो क्या होगा? एक बेहतर विचार नहीं होगा:

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

5
मुझे लगता है Math.Abs()कि बेमानी है। जब से आपने यह सुनिश्चित किया है min >= max, तब max - minवैसे भी एक गैर-नकारात्मक संख्या होनी चाहिए।
ब्रायन रेइश्चल

1

यदि आपको रेंज में एक यादृच्छिक संख्या की आवश्यकता है [ 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)

इसके बजाय उपयोग करें:

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;
        }
    }
}

2
अच्छी बात है, लेकिन इस प्रस्ताव का परिणाम दूसरे उदाहरणों की तरह तिरछा वितरण है, यहां stackoverflow.com/a/3365388/3922292
Piotr Falkowski

0

यदि आप इसे लूप में कहते हैं तो एक ही यादृच्छिक संख्या उत्पन्न करने के बारे में एक निफ्टी समाधान लूप के बाहर नए रैंडम () ऑब्जेक्ट को एक वैश्विक चर के रूप में घोषित करना है।

ध्यान दें कि यदि आपको एक लूप में इसे चलाने जा रहे हैं, तो आपको GetRandomInt फ़ंक्शन के बाहर रैंडम वर्ग के अपने उदाहरण को घोषित करना होगा।

"ऐसा क्यों है?" तुम पूछो।

ठीक है, रैंडम वर्ग वास्तव में छद्म यादृच्छिक संख्या उत्पन्न करता है, जिसमें रैंडमाइज़र सिस्टम समय के लिए "बीज" होता है। यदि आपका लूप पर्याप्त रूप से तेज़ है, तो सिस्टम क्लॉक का समय रैंडमाइज़र के लिए अलग नहीं दिखाई देगा और रैंडम वर्ग का प्रत्येक नया उदाहरण उसी बीज से शुरू होगा और आपको एक ही छद्म रैंडम नंबर देगा।

स्रोत यहां है: http://www.whypad.com/posts/csharp-get-a-random-number-between-x-and-y/412/


यह एक टिप्पणी के रूप में बेहतर है, क्योंकि यह ओपी के वास्तविक प्रश्न का उत्तर देने का प्रयास भी नहीं करता है।
b1nary.atr0phy

0

एक स्थिर रैंडम का उपयोग करें या संख्याओं को सिस्टम क्लॉक सीडिंग के कारण तंग / तेज छोरों में दोहराते हैं।

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);
    }
    //=-------------------------------------------------------------------
 }

इसे भी देखें: https://docs.microsoft.com/en-us/dotnet/api/system.random?view=netframework-4.8


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.