두 개의 두 숫자 사이의 난수
2 복식 사이에 난수를 생성 할 수 있습니까?
예:
public double GetRandomeNumber(double minimum, double maximum)
{
return Random.NextDouble(minimum, maximum)
}
그런 다음 다음과 같이 호출합니다.
double result = GetRandomNumber(1.23, 5.34);
모든 의견을 부탁드립니다.
예.
Random.NextDouble은 0과 1 사이의 배가를 반환합니다. 그런 다음 그 범위에 곱할 수있는 범위 (최대 값과 최소값의 차이)를 곱한 다음 기본 (최소)에 더합니다.
public double GetRandomNumber(double minimum, double maximum)
{
Random random = new Random();
return random.NextDouble() * (maximum - minimum) + minimum;
}
실제 코드는 임의의 정적 멤버 여야합니다. 이렇게하면 난수 생성기 생성 비용이 절약되고 GetRandomNumber를 매우 자주 호출 할 수 있습니다. 모든 통화에서 새로운 RNG를 초기화하기 때문에 시스템 시간이 통화간에 변경되지 않을 정도로 빠르게 전화를 걸면 RNG는 정확히 동일한 타임 스탬프를 시드하고 동일한 난수 스트림을 생성합니다.
Johnny5는 확장 메소드 작성을 제안했습니다. 이 작업을 수행하는 방법을 보여주는보다 완전한 코드 예제는 다음과 같습니다.
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
재사용하십시오.
가장 간단한 방법은 단순히 0과 두 숫자의 차이 사이의 난수를 생성하는 것입니다. 그런 다음 두 숫자 중 작은 숫자를 결과에 추가하십시오.
조심하십시오 : random
예를 들어 내부 루프를 생성하는 경우 루프 안에 선언을 for(int i = 0; i < 10; i++)
넣지 마십시오 new Random()
.
에서 MSDN :
난수 생성은 시드 값에서 시작합니다. 동일한 시드가 반복적으로 사용되면 동일한 일련의 숫자가 생성됩니다. 다른 시퀀스를 생성하는 한 가지 방법은 시드 값을 시간에 따라 다르게하여 새로운 각 인스턴스 인 Random에 대해 다른 시리즈를 생성하는 것입니다. 기본적으로 Random 클래스의 매개 변수가없는 생성자는 시스템 시계를 사용하여 시드 값을 생성합니다.
따라서이 사실을 바탕으로 다음과 같이하십시오.
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));
}
이 방법을 사용하면 다른 이중 값을 얻을 수 있습니다.
다음과 같은 코드를 사용할 수 있습니다.
public double getRandomNumber(double minimum, double maximum) {
return minimum + randomizer.nextDouble() * (maximum - minimum);
}
당신은 이것을 할 수 있습니다 :
public class RandomNumbers : Random
{
public RandomNumbers(int seed) : base(seed) { }
public double NextDouble(double minimum, double maximum)
{
return base.NextDouble() * (maximum - minimum) + minimum;
}
}
값 중 하나가 음수이면 어떻게 되나요? 더 나은 아이디어는 아닙니다 :
double NextDouble(double min, double max)
{
if (min >= max)
throw new ArgumentOutOfRangeException();
return random.NextDouble() * (Math.Abs(max-min)) + min;
}
[ 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;
}
}
}
나는 파티에 조금 늦었지만 일반적인 솔루션을 구현해야했으며 솔루션 중 어느 것도 내 요구를 충족시킬 수 없다는 것이 밝혀졌습니다.
허용되는 솔루션은 작은 범위에 적합합니다. 그러나 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 사이의 임의의 배가 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);
}
일부 테스트 :
Here are the sorted results of generating 10,000 random double numbers between 0 and Double.MaxValue
with both strategies. The results are displayed with using logarithmic scale:
Though the linear random values seem to be wrong at first glance the statistics show that none of them are "better" than the other: even the linear strategy has an even distribution and the average difference between the values are pretty much the same with both strategies.
Playing with different ranges showed me that the linear strategy gets to be "sane" with range between 0 and ushort.MaxValue
with a "reasonable" minimum value of 10.78294704 (for ulong
range the minimum value was 3.03518E+15; int
: 353341). These are the same results of both strategies displayed with different scales:
Edit:
Recently I made my libraries open source, feel free to see the RandomExtensions.NextDouble
method with the complete validation.
About generating the same random number if you call it in a loop a nifty solution is to declare the new Random() object outside of the loop as a global variable.
Notice that you have to declare your instance of the Random class outside of the GetRandomInt function if you are going to be running this in a loop.
“Why is this?” you ask.
Well, the Random class actually generates pseudo random numbers, with the “seed” for the randomizer being the system time. If your loop is sufficiently fast, the system clock time will not appear different to the randomizer and each new instance of the Random class would start off with the same seed and give you the same pseudo random number.
Source is here : http://www.whypad.com/posts/csharp-get-a-random-number-between-x-and-y/412/
Use a static Random or the numbers tend to repeat in tight/fast loops due to the system clock seeding them.
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);
}
//=-------------------------------------------------------------------
}
See also : https://docs.microsoft.com/en-us/dotnet/api/system.random?view=netframework-4.8
Random random = new Random();
double NextDouble(double minimum, double maximum)
{
return random.NextDouble()*random.Next(minimum,maximum);
}
참고URL : https://stackoverflow.com/questions/1064901/random-number-between-2-double-numbers
'Programing' 카테고리의 다른 글
안드로이드 이미지 캐싱 (0) | 2020.06.20 |
---|---|
스칼라에서 환경 변수를 읽는 방법 (0) | 2020.06.20 |
UIPanGestureRecognizer-세로 또는 가로 만 (0) | 2020.06.20 |
LINQ To Entity [duplicate] 세션에서 다른 스레드가 실행 중이므로 새 트랜잭션이 허용되지 않습니다. (0) | 2020.06.20 |
배경 이미지가로드되었는지 어떻게 확인할 수 있습니까? (0) | 2020.06.19 |