Как я могу получить случайное время между Теперь и некоторый предыдущий момент времени (например, 1 час назад)?

Я пытаюсь сделать дополнительный метод, который позволяет мне создавать случайное время между Теперь, и некоторый пользователь запросил исторический момент времени в форме TimeSpan.

Например: случайное время между теперь и 1 час назад.

Так, я придумал следующее Random(..) дополнительный метод.

Я думал для создания случайного семени НЕ статичным, но если я называю этот метод МНОГО и БЫСТРО (например, в цикле), затем я думал семя (который основан на времени), не действительно случайно для действительно быстрых вызовов. это верно? (это, кажется, когда я проверяю свои результаты),

public static DateTimeOffset Random(this DateTimeOffset value, TimeSpan timeSpan)
{
    var random = new Random();
    DateTimeOffset minDateTime = value.Subtract(timeSpan);
    int range = ((DateTime.Today - minDateTime)).Hours;
    return minDateTime.AddHours(random.Next(range));
}
5
задан Pure.Krome 23 December 2009 в 12:14
поделиться

3 ответа

Как говорили другие, проблема в том, что новый Random() использует текущее время для формирования семени, и вы получаете одно и то же количество раз.

В основном, вы хотите создать относительно небольшое количество экземпляров. Так как Random не является потокобезопасным, вам нужно ThreadStatic или ThreadLocal - последний является новым для .NET 4.0. Вот пример класса StaticRandom (с использованием .NET 4.0), который позволяет использовать свойство Instance для получения действительного экземпляра для данного потока. Обратите внимание, что при инициализации типа счетчик устанавливается с текущего времени. Затем он используется для последовательных семян.

using System;
using System.Threading;

public static class StaticRandom
{
    private static int seed;

    private static ThreadLocal<Random> threadLocal = new ThreadLocal<Random>
        (() => new Random(Interlocked.Increment(ref seed)));

    static StaticRandom()
    {
        seed = Environment.TickCount;
    }

    public static Random Instance { get { return threadLocal.Value; } }
}

Тогда вы можете просто использовать StaticRandom.Instance всякий раз, когда вам нужен экземпляр Random.

Теперь, чтобы вернуться к исходному вопросу, не совсем понятно, что делает ваш текущий метод расширения. Почему вы вообще используете DateTime.today? Я подозреваю, что Вы хотите что-то вроде:

public static DateTimeOffset Random(this DateTimeOffset value, TimeSpan timeSpan)
{
    double seconds = timeSpan.TotalSeconds * StaticRandom.Instance.NextDouble();

    // Alternatively: return value.AddSeconds(-seconds);
    TimeSpan span = TimeSpan.FromSeconds(seconds);
    return value - span;
}

Однако, это даст Вам совершенно случайное время - оно почти обязательно будет отчасти, например, через миллисекунду. Это нормально, или Вы фактически хотите, чтобы это было точное количество секунд (или минут, или часов), исходя из исходного времени?

.
9
ответ дан 18 December 2019 в 11:57
поделиться

Каждый раз при вызове метода используйте объект Random, созданный/инициализированный один раз и , а не . Другой вариант - передавать экземпляр Random в метод при его вызове.

Также можно создавать перегрузки, которые позволяют делать любую из вышеперечисленных опций:

public static DateTimeOffset Random(this DateTimeOffset value, TimeSpan timeSpan)
{
    if (_threadStaticRng == null)
        _threadStaticRng = new Random();

    return value.Random(timeSpan, _threadStaticRng);
}

public static DateTimeOffset Random(
    this DateTimeOffset value, TimeSpan timeSpan, Random rng)
{
    DateTimeOffset minDateTime = value.Subtract(timeSpan);
    int range = ((DateTime.Today - minDateTime)).Hours;
    return minDateTime.AddHours(rng.Next(range));
}

[ThreadStatic]
private static Random _threadStaticRng;
7
ответ дан 18 December 2019 в 11:57
поделиться

Вам нужно посадить генератор случайных чисел. Хорошей практикой было бы сделать следующее:

var random = new Random((int)DateTime.Now.Ticks);

Это должно сделать его более случайным для Вас.

Вы также можете создать генератор случайных чисел как статическую переменную класса, чтобы не нужно было каждый раз его инстанцировать.

.
-1
ответ дан 18 December 2019 в 11:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: