Development/Java

[JAVA] 랜덤 퍼센트 계산하는 클래스(?)

반응형

게임이나 뭐 확률 관련된 개발을 하다보면


뭔가 퍼센트로 어떤 동작이 실행됐냐 안됐냐를 확인하고 싶을때가 있다


input : percent

output : true / false


ex)

input : 0.8f

output : true


이런식으로 말이다.


이럴때!! 쓰는 간단한 클래스




public class ChanceSupport {

public static boolean percent(double percent) {
        return percent > ThreadLocalRandom.current().nextDouble(0, 1);
    }
    }
}


double로 받은 percent 변수가 랜덤으로 뽑은 double 변수와 비교해서 그보다 작은지를 확인한다


ex)

랜덤으로 뽑은 값 : 0~1

퍼센트로 지정한 값 : 0.8


if(0.8 > 3.1323) ...


이 될테니, 0.8이 넘는 수만 false가 떨어질 것이고, 나머지 0~0.8 사이는 true가 떨어질 것이다.



ThreadLocalRandom을 사용해서 쓰레드 세이프한 확률을 보장해준다

(Random 클래스의 경우 멀티쓰레드에서 사용할 경우 Seed 값이 겹치는 경우가 있으므로 완전한 Random값이라고 할 수 없다)


stackoverflow 인용(https://stackoverflow.com/questions/23396033/random-over-threadlocalrandom)

Normally to generate Random numbers, we either do Create an instance of java.util.Random OR Math.random() - which internally creates an instance of java.util.Random on first invocation. However in a concurrent applications usage of above leads to contention issues

Random is thread safe for use by multiple threads. But if multiple threads use the same instance of Random, the same seed is shared by multiple threads. It leads to contention between multiple threads and so to performance degradation.

ThreadLocalRandom is solution to above problem. ThreadLocalRandom has a Random instance per thread and safeguards against contention.


사용 : boolean isSuccess = ChanceSupport.percent(0.8f);


확률적으로 잘 동작하나 테스트



@RunWith(SpringRunner.class)
@SpringBootTest
public class PercentTest {

    private final Logger logger = getLogger(this.getClass());

    @Test
    public void percent() {
        int _true = 0;
        int _false = 0;
        for (int i = 0; i < 10000000; i++) {
            boolean result = ChanceSupport.percent(0.9f);
            if (result) {
                _true++;
            } else {
                _false++;
            }
        }
        logger.info("true : {} false : {}", _true, _false);
    }
}


1천만개의 시행을 해서 돌려보면,


c.g.b.PercentTest : true : 8999757 false : 1000243


로, 얼추 90%에 가까운 숫자가 나온다.

반응형