给定一个公平硬币的函数,为有偏差的硬币编写一个函数?

发布于 2024-08-17 02:53:23 字数 548 浏览 4 评论 0原文

我在进行一些审查时遇到了这个报道的面试问题(以下引用是我发现的有关该问题的所有信息):

给定一个公平硬币的函数, 为有偏差的硬币编写一个函数 返回正面 1/n 次(n 是 参数)

乍一看我写道:

int biased_coin(n) { //0=Tails, 1=Heads
  int sum = 0;

  if(n==1)
    return 1;

  for(int i=0;i<n;i++) {
    sum += unbiased(); //unbiased returns 0 50% of the time and 1 50% of the time
  }

  if(sum == 1)
    return 1;

  return 0;
}

但这显然行不通。例如,对于 n=4,它确实有效:因为 4 次抛掷得到单个正面的概率是 4/(2^4)=1/4。但对于 n=3,3/(2^3)!=1/3。

假设您不能使用随机数生成器,那么实现此类操作的正确方法是什么?

I came across this reported interview question when doing some reviewing (the following quote is all the info I found about the problem):

Given a function for a fair coin,
write a function for a biased coin
that returns heads 1/n times (n is a
param)

At first glance I wrote:

int biased_coin(n) { //0=Tails, 1=Heads
  int sum = 0;

  if(n==1)
    return 1;

  for(int i=0;i<n;i++) {
    sum += unbiased(); //unbiased returns 0 50% of the time and 1 50% of the time
  }

  if(sum == 1)
    return 1;

  return 0;
}

But this obviously doesn't work. For n=4, for instance, it does work: since the probability of getting a single Head given 4 tosses is 4/(2^4)=1/4. But for say n=3, 3/(2^3)!=1/3.

What is the proper way to implement something like this assuming you can't use a random number generator?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

不打扰别人 2024-08-24 02:53:24

由于 N 的大多数值不是 2 的幂,因此严格来说不可能保证任意次数的硬币抛掷的概率为 1/N。相反,您必须满足于接近您所需精度的 1/N 的结果。但是,嘿,这对你来说无论如何都是抛硬币。

为自己绘制一棵决策树,其根部有 2 个分支(标记为 H 和 T),然后每个节点有 2 个分支(也标记为 H 和 T),直到达到足够的叶节点来满足您的准确性要求。用您想要的值标记叶子的右侧(为您)部分,例如,如果 N=3,则为 1,2,3。然后,每个叶子定义一条从根开始的路由,例如 HHHTTHH(或其他)。这些定义了导致“3”的投掷顺序。

我将把编码留给你。

Since most values of N are not powers of 2 it's not strictly possible to guarantee a probability of 1/N from any number of coin tosses. Instead you'll have to settle for something which approaches 1/N to your desired accuracy. But hey, that's coin tossing for you anyway.

Draw yourself a decision tree with 2 branches at the root (labelled H and T), then 2 branches at each node (also labelled H and T), until you reach enough leaf nodes to satisfy your accuracy requirements. Label the right (for you) fraction of leaves with the values you want, eg 1,2,3 if N=3. Each leaf then defines a route from the root, such as HHHTTHH (or whatever). These define the sequence of tosses which result in a '3'.

I'll leave the coding to you.

动次打次papapa 2024-08-24 02:53:23

假设:

int fairCoinToss();

正面返回 1,反面返回 2,写入:

int biasedCoinToss(int n);

其中正面 (1) 将出现 1/n 的时间,这应该有效:

int biasedCoinToss(int n) {
  if (n == 1) {
    return 1; // 1/1 = 1 = always heads
  } else if (n == 2) {
    return fairCoinToss(); // 1/2 = 50% = fair coint oss
  }
  int r = random_number(n);
  return r == 0 ? 1 : 0;
}

其中 random_number(n) 生成一个公平的随机整数 i,使得<代码> 0 <= i < n。因此,random_number(3) 为 0、1 或 2。假设均匀分布,则 1/3 的时间将出现值 0。

当然,我们不能使用本机随机数生成器,但无论如何我们可以创建一个。 fairCoinToss() 随机生成 1 或 0。可以组合多次抛硬币来生成更大的数字。例如:

fairCoinToss() << 1 | fairCoinToss()

将生成:

00 = 0
01 = 1
10 = 2
11 = 3

根据定义,它是 0 到 3 之间的随机数 (n = 4)。

如果 n 是 2 的幂就可以,但也不一定。然而,这很容易满足。假设 n = 5。我们最多可以生成一个从 0 到 7 的随机数。如果您“重新滚动”5、6 或 7,直到获得 0 到 4 范围内的数字,那么您就(非确定性地)构造了一个0到4之间均匀分布的随机数,满足要求。

代码看起来像这样:

int random_number(int n) {
  int ret;
  do {
    int limit = 2;
    ret = fairCoinToss();
    while (limit < n) {
      ret <<= 1;
      ret |= fairCoinToss();
      limit <<= 1;
    }
  } while (ret >= n);
  return ret;
}

Assuming:

int fairCoinToss();

returns 1 for heads and 2 for tails, writing:

int biasedCoinToss(int n);

where heads (1) will appear 1/n of the time this should work:

int biasedCoinToss(int n) {
  if (n == 1) {
    return 1; // 1/1 = 1 = always heads
  } else if (n == 2) {
    return fairCoinToss(); // 1/2 = 50% = fair coint oss
  }
  int r = random_number(n);
  return r == 0 ? 1 : 0;
}

where random_number(n) generates a fair random integer i such that 0 <= i < n. So random_number(3) is 0, 1 or 2. Assuming even distribution, value 0 will come out 1/3 of the time.

Of course we can't use a native random number generator but we can create one anyway. fairCoinToss() randomly generates a 1 or 0. Multiple coin tosses can be combined to generate a larger number. For example:

fairCoinToss() << 1 | fairCoinToss()

will generate:

00 = 0
01 = 1
10 = 2
11 = 3

which by definition is a random number from 0 to 3 (n = 4).

That's fine if n is a power-of-2 but it isn't necessarily. That's easy enough to cater for however. Assume n = 5. At best we can generate a random number from 0 to 7. If you "reroll" 5, 6 or 7 until you get a number in the range of 0 to 4 then you have (non-deterministically) constructed a random number fairly distributed from 0 to 4 inclusive, satisfying the requirement.

Code for that looks something like this:

int random_number(int n) {
  int ret;
  do {
    int limit = 2;
    ret = fairCoinToss();
    while (limit < n) {
      ret <<= 1;
      ret |= fairCoinToss();
      limit <<= 1;
    }
  } while (ret >= n);
  return ret;
}
ぇ气 2024-08-24 02:53:23

这个怎么样:
1.找出n的二进制表示
2. 翻转公平硬币logn次。每一次翻转对应一个位。
3. 如果翻转的结果大于n的值,则重新滚动。
4. 如果结果为0,则返回正面。
5. 否则,返回尾部。

How about this:
1. Find out the binary representation of n
2. Flip the fair coin logn times. Each flip corresponds to a bit.
3. If the result of the flip is greater than the value of n, reroll.
4. If the result is 0, return heads.
5. Otherwise, return tails.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文