Генерация случайного десятичного числа в C#

Вы можете добавить параметр настроек в методе $.post(), который равен методу $.ajax(), где вы можете установить опцию:

settings: {
 "async": "false"
}

Таким образом, вы можете сделать несколько запросов AJAX на странице.

59
задан abatishchev 2 November 2011 в 15:15
поделиться

5 ответов

РЕДАКТИРОВАНИЕ: Удаленная старая версия

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

Примечание, что распределение десятичных чисел здесь не универсально .

/// <summary>
/// Returns an Int32 with a random value across the entire range of
/// possible values.
/// </summary>
public static int NextInt32(this Random rng)
{
     int firstBits = rng.Next(0, 1 << 4) << 28;
     int lastBits = rng.Next(0, 1 << 28);
     return firstBits | lastBits;
}

public static decimal NextDecimal(this Random rng)
{
     byte scale = (byte) rng.Next(29);
     bool sign = rng.Next(2) == 1;
     return new decimal(rng.NextInt32(), 
                        rng.NextInt32(),
                        rng.NextInt32(),
                        sign,
                        scale);
}
45
ответ дан Jon Skeet 24 November 2019 в 18:31
поделиться

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

существует два определения однородно случайного: дискретный однородно случайный и непрерывный однородно случайный .

Дискретно однородно случайный имеет смысл для генератора случайных чисел, который имеет конечное число различных возможных результатов. Например, генерируя целое число между 1 и 10. Вы тогда ожидали бы, что вероятность получения 4 совпадает с получением 7.

Непрерывно однородно случайный имеет смысл, когда генератор случайных чисел генерирует числа в диапазоне. Например, генератор, который генерирует вещественное число между 0 и 1. Вы тогда ожидали бы, что вероятность получения числа между 0 и 0.5 совпадает с получением числа между 0,5 и 1.

, Когда генератор случайных чисел генерирует числа с плавающей запятой (который является в основном что Система. Десятичное число - это просто с плавающей точкой, которые базируются 10), спорно, каково надлежащее определение однородно случайного:

С одной стороны, так как число с плавающей запятой представлено постоянным числом битов в компьютере, очевидно, что существует конечное число возможных результатов. Таким образом, можно было утверждать, что надлежащее распределение является дискретным непрерывным распределением с каждым представимым числом, имеющим ту же вероятность. Это в основном, что Jon Skeet и John Leidegren делает реализация.

, С другой стороны, можно было бы утверждать, что, так как число с плавающей запятой, как предполагается, является приближением к вещественному числу, мы были бы более обеспечены путем попытки приблизить поведение непрерывного генератора случайных чисел - даже при том, что фактический RNG, на самом деле дискретно. Это - поведение, которое Вы получаете от Случайного. NextDouble (), где - даже при том, что существует приблизительно столько же представимых чисел в диапазоне 0.00001-0.00002 сколько существует в диапазоне 0.8-0.9, Вы, в тысячу раз более вероятно, получите число во втором диапазоне - как Вы ожидали бы.

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

Вот простое изменение ответа Jon Skeet, который равномерно распределен между 0 и 1 (я снова использую его NextInt32 () дополнительный метод):

public static decimal NextDecimal(this Random rng)
{
     return new decimal(rng.NextInt32(), 
                        rng.NextInt32(),
                        rng.Next(0x204FCE5E),
                        false,
                        0);
}

Вы могли также обсудить, как получить равномерное распределение по всему диапазону десятичных чисел. Существует, вероятно, более легкий способ сделать это, но эта небольшая модификация ответ John Leidegren должна произвести относительно равномерное распределение:

private static int GetDecimalScale(Random r)
{
  for(int i=0;i<=28;i++){
    if(r.NextDouble() >= 0.1)
      return i;
  }
  return 0;
}

public static decimal NextDecimal(this Random r)
{
    var s = GetDecimalScale(r);
    var a = (int)(uint.MaxValue * r.NextDouble());
    var b = (int)(uint.MaxValue * r.NextDouble());
    var c = (int)(uint.MaxValue * r.NextDouble());
    var n = r.NextDouble() >= 0.5;
    return new Decimal(a, b, c, n, s);
}

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

, Который означает, что мы должны получить масштаб 0 90% времени - начиная с, тот диапазон содержит 90% возможного диапазона - масштаб 1 9% времени, и т.д.

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

9
ответ дан Community 24 November 2019 в 18:31
поделиться

Я озадачил с этим некоторое время. Это является лучшим, я мог придумать:

public class DecimalRandom : Random
    {
        public override decimal NextDecimal()
        {
            //The low 32 bits of a 96-bit integer. 
            int lo = this.Next(int.MinValue, int.MaxValue);
            //The middle 32 bits of a 96-bit integer. 
            int mid = this.Next(int.MinValue, int.MaxValue);
            //The high 32 bits of a 96-bit integer. 
            int hi = this.Next(int.MinValue, int.MaxValue);
            //The sign of the number; 1 is negative, 0 is positive. 
            bool isNegative = (this.Next(2) == 0);
            //A power of 10 ranging from 0 to 28. 
            byte scale = Convert.ToByte(this.Next(29));

            Decimal randomDecimal = new Decimal(lo, mid, hi, isNegative, scale);

            return randomDecimal;
        }
    }

Редактирование: Как отмечено в комментариях lo, середине и привет никогда не может содержать интервал. MaxValue так полный спектр Десятичных чисел не возможен.

2
ответ дан Daniel Ballinger 24 November 2019 в 18:31
поделиться

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

using System.Security.Cryptography;

public static decimal Next(decimal max)
{
    // Create a int array to hold the random values.
    Byte[] randomNumber = new Byte[] { 0,0 };

    RNGCryptoServiceProvider Gen = new RNGCryptoServiceProvider();

    // Fill the array with a random value.
    Gen.GetBytes(randomNumber);

    // convert the bytes to a decimal
    return new decimal(new int[] 
    { 
               0,                   // not used, must be 0
               randomNumber[0] % 29,// must be between 0 and 28
               0,                   // not used, must be 0
               randomNumber[1] % 2  // sign --> 0 == positive, 1 == negative
    } ) % (max+1);
}

пересмотренный для использования другого десятичного конструктора для предоставления лучшего диапазона чисел

public static decimal Next(decimal max)
{
    // Create a int array to hold the random values.
    Byte[] bytes= new Byte[] { 0,0,0,0 };

    RNGCryptoServiceProvider Gen = new RNGCryptoServiceProvider();

    // Fill the array with a random value.
    Gen.GetBytes(bytes);
    bytes[3] %= 29; // this must be between 0 and 28 (inclusive)
    decimal d = new decimal( (int)bytes[0], (int)bytes[1], (int)bytes[2], false, bytes[3]);

        return d % (max+1);
    }
2
ответ дан Muad'Dib 24 November 2019 в 18:31
поделиться
static decimal GetRandomDecimal()
    {

        int[] DataInts = new int[4];
        byte[] DataBytes = new byte[DataInts.Length * 4];

        // Use cryptographic random number generator to get 16 bytes random data
        RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

        do
        {
            rng.GetBytes(DataBytes);

            // Convert 16 bytes into 4 ints
            for (int index = 0; index < DataInts.Length; index++)
            {
                DataInts[index] = BitConverter.ToInt32(DataBytes, index * 4);
            }

            // Mask out all bits except sign bit 31 and scale bits 16 to 20 (value 0-31)
            DataInts[3] = DataInts[3] & (unchecked((int)2147483648u | 2031616));

          // Start over if scale > 28 to avoid bias 
        } while (((DataInts[3] & 1835008) == 1835008) && ((DataInts[3] & 196608) != 0));

        return new decimal(DataInts);
    }
    //end
1
ответ дан 24 November 2019 в 18:31
поделиться
Другие вопросы по тегам:

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