最近遇到一个有趣的需求,大概意思就是:编写一个方法,其输出是true或者false,并且该方法调用量很大,我们无法预测每次调用该方法究竟会产生什么结果,但产生true的概率是(或者说非常接近)预先设定好的(比如20%)。
为了实现这个需求,可以采取这样一种思路:
1,建立一个BitSet,size设为100。然后随机产生X个下标,然后将这些下标对应的位置设为true。
2,每次调用该方法时,再产生一个随机数作为下标,然后以此下标取得bitset中指定位置的值,返回。
下面贴一个Java的实现:
首先是产生指定个数的随机下标,TreeSet的一个良好特性就是对于重复的元素,将不会被加入其中
- private List<Integer> makeRndNumbers(int count, int boundry) {
-
TreeSet<Integer> set = new TreeSet<Integer>();
-
while(set.size() < count) {
- set.add(Math.abs(secRandom.nextInt()) % boundry);
- }
-
-
return new ArrayList<Integer>(set);
- }
假设这个类命名为PercentChoice,其构造方法如下,这里使用了SecureRandom类,这是Java内置的一个安全的随机数发生器。
- public PercentChoice(int percentage) {
-
try {
-
secRandom = SecureRandom.getInstance("SHA1PRNG");
- secRandom.setSeed(System.currentTimeMillis());
-
} catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
-
-
for(Integer i : makeRndNumbers(percentage, 100)) {
-
bitSet.set(i, true);
- }
- }
这个方法的代码就非常容易了
- public boolean getOneChoice() {
-
return bitSet.get(Math.abs(secRandom.nextInt()) % 100);
- }
最后写个测试的方法
- public static void main(String[] args) throws InterruptedException {
-
PercentChoice pc = new PercentChoice(20);
-
int hits = 0;
-
int times = 10000;
-
for(int i = 0; i < times; i++) {
-
if(pc.getOneChoice()) {
- hits++;
- }
- }
-
System.out.println("Hits percentage " + (double)hits * 100 / (double)times + " %");
- }
在我的机器上反复运行这个测试,其实验结果总是在20%的左右抖动,代码完全满足了需求。
本文转自 kevx 51CTO博客,原文链接:http://blog.51cto.com/spinlock/447867,如需转载请自行联系原作者
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。