java三角形v体积等,Java- Math.random():选择13 x 13三角形数组的元素

这篇博客讨论了如何在乘法游戏中确保所有组合被等频率地抽取。作者提出使用一个随机数生成策略,通过计算最近的三角数来确定两个数的值,以达到均匀分布的效果。这种方法涉及到数学和概率论,解决了在0到12之间随机选择两个数时,平方对出现频率不均的问题。解决方案包括寻找三角数序列的规律,并利用平方根公式快速找到小于给定随机数的最大三角数。
摘要由CSDN通过智能技术生成

Edit: This problem is solved. If you would like to help on another problem, please visit Java Biasing Random Numbers in a Triangular Array.

I'm doing a multiplication game, so I pick 2 numbers between 0 and 12 inclusive. If I do that like this:

int num1 = (int)(Math.random() * 13);

int num2 = (int)(Math.random() * 13);

the squares (0x0,1x1,2x2,etc) are picked half the time (because 1x2 is the same as 2x1). How can I make all combinations picked at the same frequency? There are 91 possible combinations (n(n+1)/2). If it helps, here is a 13 by 13 triangular array:

{{0},

{0,0},

{0,0,0},

{0,0,0,0},

{0,0,0,0,0},

{0,0,0,0,0,0},

{0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0,0,0,0,0},

{0,0,0,0,0,0,0,0,0,0,0,0,0}};

I've tried picking the first number and giving the second number a 50% chance of being the first one. This did not work. I tried giving the second number a 1/91 chance of being the first one. This resulted in the smaller numbers being picked a far greater number of times (around 7/91 of the time; it is a smooth, curved increase). I thought about having a single random number: int roll = random.next(91) and then splitting it into 2 entries (like a coordinate (x,y)) but I could not figure out how to split it.

解决方案

The int roll = random.next(91) strategy will work just fine. You get guaranteed, worry-free uniform distribution, and better performance to boot, since you're only picking 1 random number. You simply need to find a formula that identifies where one "row" ends and another begins. Look for the pattern:

0, 1, 3, 6, 10, 15, ...

There's a reason they're called "triangular numbers..."

Let's flesh this out a bit more. You want to actually find the nearest triangle number smaller than the random roll that you picked: that gets you to the right row, and the difference of that triangle number and roll gets you the offset into that row.

Given that the nth triangle number is given by n*(n+1)/2, how do you find the largest one smaller than roll? Given the small size of the array, a naïve implementation should be plenty fast:

int largestTriangleNumberSmallerThan(int x) {

int i = 0;

int last = 0;

while (true) {

int triangle = i*(i+1)/2;

if (triangle > x) return last;

last = triangle;

i++;

}

}

Of course, that's boring and didn't take any thought. We can do better! We can do it in constant* time, regardless of how big the input is! Start by inverting the function (we only care about the positive root, of course):

n = (Math.sqrt(8y + 1) - 1)/2

Then truncate the decimal part, and run it back through:

int largestTriangleNumberSmallerThan(int x) {

int n = (int) (Math.sqrt(8*x + 1) - 1)/2;

return n*(n+1)/2;

}

To put it all together:

int roll = random.nextInt(91);

int num1 = (int) (Math.sqrt(8*roll + 1) - 1)/2;

int num2 = roll - num1*(num1+1)/2;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值