정수 난수를 사용하여 특정 정밀도와 특정 범위에서 실수 난수를 생성 할 수 있습니까? $ RANDOM 생성자? 예를 들어 0과 1 사이의 정밀도가 4 인 실수를 어떻게 생성 할 수 있습니까?
0.1234 0.0309 0.9001 0.0000 1.0000
간단한 해결 방법 :
printf "%d04.%d04\n" $RANDOM $RANDOM
댓글
- ” 실제 난수 . 파티클 붕괴와 같은 것에 의해 생성 된 난수의 소스가 필요합니까, 아니면 의사 난수 생성기에 만족하십니까? 이러한 숫자의 암호화 또는 과학적 중요성을 적용하고 있습니까? 아니면 ” 무작위로 보이는 ” 무언가를 원하십니까?
- … 또는 실제로 ” float ” 또는 ” 플로팅을 의미합니까? 포인트 번호?
- 댓글 감사합니다. $ RANDOM을 기반으로하는 부동 소수점 숫자를위한 의사 난수 생성기가 필요합니다.
- … bash에서 메타 휴리스틱 알고리즘을 구현하기 위해
Answer
awk -v n=10 -v seed="$RANDOM" "BEGIN { srand(seed); for (i=0; i<n; ++i) printf("%.4f\n", rand()) }"
이것은 n
난수 (예제에서는 10 개)를 출력합니다. 범위 [0,1)에서 4 자리 10 진수. awk
의 rand()
함수를 사용합니다 (표준 awk
는 아니지만 가장 일반적인 awk
구현) 해당 범위에서 임의의 값을 반환합니다. 난수 생성기는 쉘의 $RANDOM
변수에 의해 시드됩니다.
awk
프로그램에 BEGIN
블록 (다른 코드 블록 없음), awk
는 표준 입력 스트림에서 입력을 읽으려고 시도하지 않습니다.
모든 OpenBSD 시스템 (또는 원래 4.2BSD에서 동일한 jot
유틸리티 가있는 시스템)에서 다음은 다음과 같습니다. 지정된대로 10 개의 임의의 숫자를 생성합니다.
jot -p 4 -r 10 0 1
Comments
- 정말 엄격하게 말하면 of
rand()
는 [0,1) 내의 부동 소수점이며, ‘ 10 진수 4 자리로 반올림했을 때 정확히 균등하게 분포되지 않을 수 있습니다. 부동 소수점이 무한 정밀도이지만 ‘ t : 임의의 비트에서 생성 될 가능성이 ‘ 일 수 있습니다. , 2 ^ N 개의 서로 다른 값이 있습니다. ‘ 1000 개 값 집합에 균일하게 매핑되지 않습니다. 하지만 이러한 의사 랜덤 플로트에 충분한 비트가 있고 ‘ 정확한 작업을 수행하지 않는 한 ‘
Answer
다른 답변에서 지적했듯이 생성에 사용할 수있는 다른 유틸리티가 있습니다. 난수. 이 답변에서는 리소스를 $RANDOM
및 몇 가지 기본적인 산술 함수로 제한합니다.
부동 소수점 숫자의 경우
printf "%s\n" $(echo "scale=8; $RANDOM/32768" | bc )
$RANDOM
는 0에서 32767 사이의 숫자 만 생성하기 때문에 최상의 정밀도를 얻을 수 있습니다. (32767 포함!)하지만, I ” 또한 bc
를 호출하여 기본 산술 함수 사용에 대한 규칙을 어겼습니다.
하지만 계속 진행하기 전에 두 가지 문제 정밀도를 살펴보고 싶습니다. 및 범위 (부동 소수점 숫자). 그 후에 정수 범위를 생성하는 방법을 살펴 보겠습니다 (정수를 생성 할 수 있다면 나중에 원하는 유틸리티를 사용하여 소수를 나눌 수 있습니다.)
정밀도
$RANDOM/32768
의 접근 방식을 취합니다. div id = “22dc039bcf”>
는 0에서 32767까지의 값을 생성하며,$RANDOM/32768
의 결과도 마찬가지로 유한 한 많은 값이됩니다. 다시 말해서, 이것은 여전히 불연속적인 랜덤 변수입니다 (컴퓨터를 사용하면 결코 그 사실에서 벗어날 수 없습니다). 이를 염두에두고printf
를 사용하여 어느 정도의 정밀도 를 달성 할 수 있습니다.
간격, 당신은 기본 32768에서 생각을 시작할 수 있습니다. 따라서 이론적으로 $RANDOM + $RANDOM*32768
는 0에서 1,073,741,823 사이의 균일 한 분포를 제공해야합니다. 그러나 명령 줄이 그 정밀도를 매우 잘 처리 할 수 있을지 의심 스럽습니다.이 특정 경우와 관련된 몇 가지 사항 :
- 일반적으로 균일하지 않은 두 개의 독립적이고 균일하게 분포 된 임의 변수의 합. 이 경우 적어도 이론적으로 말하면 (세 번째 항목 참조) 그렇습니다.
-
$RANDOM + $RANDOM*32768 = $RANDOM * ( 1 + 32768 )
를 단순화 할 수 있다고 생각하지 마세요.$RANDOM
의 두 가지 발생은 실제로 두 가지 다른 이벤트입니다. -
$RANDOM
가 어떻게 나타나는지 충분히 알지 못합니다. 이렇게 두 번 호출하면 실제로 두 개의 독립적 인 임의 이벤트가 생성되는지 확인하기 위해 생성되었습니다.
범위
$RANDOM/32768
만 고려해 보겠습니다. 범위의 숫자를 원하면 [a,b)
라고 말하면
$RANDOM/32768*(b-a) + a
원하는 범위로 이동합니다. .
정수 값 생성
먼저, [0,b)
여기서 b
는 32768
보다 작습니다. q*b
제품을 생각해보십시오. 여기서 q
는 32768/b
의 정수 부분입니다. 그런 다음 할 수있는 일은 0에서 32767 사이의 임의의 숫자를 생성하지만 q*b
보다 크거나 같은 숫자는 버리는 것입니다. 이렇게 생성 된 번호로 전화하십시오. G
그러면 G
가 0에서 q*b
범위에 속하고 분포가 균일합니다. 이제 모듈 식 산술을 적용하여이 값을 원하는 범위로 낮추십시오.
G % b
참고, 다음과 같이 무작위로 숫자를 생성합니다.
$RANDOM % b
b
가 32768
.
이를위한 bash 스크립트 작성
계산 q*b
는 고통스러워 보입니다. 하지만 실제로는 그렇지 않습니다. 다음과 같이 얻을 수 있습니다.
q*b = 32768 - ( 32768 % b )
Bash에서는
다음 코드는 0..b
범위에서 임의의 숫자를 생성합니다 (b
제외). . b=$1
m=$((32768 - $((32768 % $1)) )) a=$RANDOM while (( $a > $m )); do a=$RANDOM done a=$(($a % $1)) printf "$a\n"
부록
기술적으로 작업 할 이유가 거의 없습니다.
m=$((32768 - $((32768 % $1)) ))
다음은 동일한 작업을 수행합니다.
a=$RANDOM while (( $a > $1 )); do a=$RANDOM done printf "$a\n"
더 많은 작업이 필요하지만 컴퓨터는 빠릅니다.
더 큰 범위에서 정수 생성
이것을 알아 내도록하겠습니다. 주의가 필요하며 어떤 시점에서는 산술 연산을 처리 할 때 컴퓨터의 메모리 제한을 고려해야합니다.
최종 참고 사항
수락 된 답변은 0에서 1까지 균일하게 임의의 숫자를 생성하지 않습니다.
이를 보려면 다음을 시도해보세요.
$ for i in {1..1000}; do echo .$RANDOM; done | awk "{ a += $1 } END { print a }"
[0,1)
에 걸쳐 진정으로 균일 한 분포를 얻으려면 평균이 .
하지만 위의 스 니펫을 실행하여 볼 수 있듯이 대신 314.432
또는 . 1000 개의 숫자이므로 평균은 .322
입니다. 이 일련의 생성 된 숫자의 실제 평균은 .316362
입니다.
Perl 스크립트를 사용하여이 실제 평균을 얻을 수 있습니다.
perl -e "{ $i=0; $s=0; while ( $i<=32767 ) { $j = sprintf "%.5f", ".$i"; $j =~ s/^0\.//; print "$j\n"; $s += $j; $i++ }; printf "%.5f\n", $s/32767; }"
.$RANDOM
를 사용하는 이러한 접근 방식이 원하는 작업을 수행하지 않는지 확인하는 데 도움이되도록 여기에 정수를 추가합니다. 즉, 어떤 정수가 생성되고 어떤 정수가 모두 누락되었는지 생각하십시오. 상당히 많은 수를 건너 뜁니다. 상당수는 두 배가됩니다.
답변
쉘의 printf가 형식 (bash ksh zsh 등)이므로 내부 기본 변경 (hex-> dec)을 수행 할 수 있습니다 ([0,1)
범위에서 균일 함 0.00003 ~ 0.99997) :
printf "%.5f\n" "$(printf "0x0.%04xp1" $RANDOM)"
$RANDOM
에 대한 더 많은 호출을 결합하여 더 많은 숫자를 사용할 수도 있습니다 (0.000000001에서 0.999999999)
printf "%.9f\n" "$(printf "0x0.%08xp2" $(( ($RANDOM<<15) + $RANDOM )))"
내부 (셸에 대해) “$ RANDOM”알고리즘은 선형 피드백 시프트 레지스터 (LFSR)를 기반으로합니다. 보안 의사 난수 생성기 (CSPRNG). 더 나은 옵션은 /dev/urandom
장치의 바이트를 사용하는 것입니다.이를 위해서는 외부 8 진수 또는 16 진수 덤프를 호출해야합니다.
$ printf "%.19f\n" "0x0.$(od -N 8 -An -tx1 /dev/urandom | tr -d " ")" 0.7532810412812978029 $ printf "%.19f\n" "0x0.$(hexdump -n 8 -v -e ""%02x"" /dev/urandom)" 0.9453460825607180595
플로트를 얻기위한 매우 간단하지만 균일하지 않은 솔루션은 다음과 같습니다.
printf "0.%04d\n" $RANDOM
[0,1)
범위 (1 제외)에서 균일하게 만드는 방법 :
while a=$RANDOM; ((a>29999)); do :; done; printf "0.%04d\n" "$((a%10000))"
답변
$(( ( RANDOM % N ) + MIN ))
사용
MAX 번호와 MIN은 생성하려는 최소 번호입니다. (N
MAX는 배타적이므로 N+1
를 입력하세요. MAX, MIN을 모두 포함).
또는 $(shuf -i MIN-MAX -n 1)
를 대신 사용할 수 있습니다.
man shuf
:
-i, --input-range=LO-HI treat each number LO through HI as an input line -n, --head-count=COUNT output at most COUNT lines
-n 1
shuf의 / div>는 임의의 숫자를 하나만 생성 함을 의미합니다.
이것은 앞에 0이있는 0 ~ 9999 사이의 임의의 숫자를 생성합니다. printf
사용 (결과적으로 숫자 1
는 배타적 임).
printf "0.%04d\n" $(( RANDOM % 1000 )) 0.0215
댓글
- 또한 N이 32767의 제수 ($ RANDOM의 상한) 인 경우를 제외하고는 주어진 범위에서 진정한 난수를 생성하지 않습니다.
Answer
배시에서
bc -l <<< "scale=4 ; $((RANDOM % 10000 ))/10000"
여기서 1/10000
는 무작위입니다. 정밀도 및 4
숫자 출력 정밀도
답변
zsh
에는 iv id =”2002b32e4d에 rand48()
산술 함수 (erand48()
표준 함수에 대한 래퍼)가 있습니다. “>
모듈 :
zmodload zsh/mathfunc printf "%.4f\n" $((rand48()))
$RANDOM
는 15 비트이며 의사 랜덤이며 재현 가능합니다. bash
5.1+는 사용 가능한 실제 임의 소스를 기반으로 더 안전한 32 비트 정수 $SRANDOM
를 갖습니다. 부동 소수점 산술을 지원하지 않지만 최소한 awk
“의 의사 난수 생성기를 시드하는 데 사용할 수 있습니다 (그렇지 않으면 기본적으로 time()
) :
echo "$SRANDOM" | awk " { srand($1) for (i = 0; i < 20; i++) printf "%.4f\n", rand() }"
(아직 32 비트 엔트로피에 불과하며 awk
는 해당 시드를 기반으로 결정 론적 의사 랜덤 생성을 수행합니다.)