Bash : $ RANDOM을 사용하여 난수를 생성하는 방법

정수 난수를 사용하여 특정 정밀도와 특정 범위에서 실수 난수를 생성 할 수 있습니까? $ 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 진수. awkrand() 함수를 사용합니다 (표준 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) 여기서 b32768보다 작습니다. q*b 제품을 생각해보십시오. 여기서 q32768/b의 정수 부분입니다. 그런 다음 할 수있는 일은 0에서 32767 사이의 임의의 숫자를 생성하지만 q*b보다 크거나 같은 숫자는 버리는 것입니다. 이렇게 생성 된 번호로 전화하십시오. G 그러면 G가 0에서 q*b 범위에 속하고 분포가 균일합니다. 이제 모듈 식 산술을 적용하여이 값을 원하는 범위로 낮추십시오.

G % b 

참고, 다음과 같이 무작위로 숫자를 생성합니다.

$RANDOM % b 

b32768.

이를위한 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 1shuf의 / 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는 해당 시드를 기반으로 결정 론적 의사 랜덤 생성을 수행합니다.)

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다