难道" N *(RAND()/ RAND_MAX)QUOT;使偏态随机数的分布? [英] Does "n * (rand() / RAND_MAX)" make a skewed random number distribution?

查看:641
本文介绍了难道" N *(RAND()/ RAND_MAX)QUOT;使偏态随机数的分布?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想找到用C获得随机数(虽然最多,我将要使用它的0-20值,更有可能仅0-8)的unskewed方式。我已经看到了这个公式,但在运行一些测试后,我不知道它是否歪斜与否。任何帮助吗?

下面是所使用的全部功能:

  INT randNum()
{
    返回1 +(int)的(10.0 *(兰特()/(RAND_MAX + 1.0)));
}

我播种它使用:

  unsigned int类型iseed =(无符号整数)时间(NULL);
函数srand(iseed);

在以下任一建议拒绝我,我试过

工作

  INT希腊;
为(J = 0; J< 50000; J ++)
{
希腊= rand_lim(5);
的printf(%d个,希腊);
希腊=(INT)(NUM *(RAND()/(RAND_MAX + 1.0)));
INT多哥=号[希腊]
号码[希腊] =多哥+ 1;
}

当我注释掉的printf它停止工作,使我有相同数量的50000倍。


解决方案

是的,这是扭曲的,除非你RAND_MAX恰好是10的倍数。

如果你从0拿数字来RAND_MAX,并尝试将其分成10堆,你真的只有三种可能性:


  1. RAND_MAX是10的倍数,而桩出来偶数。

  2. RAND_MAX不是10的倍数,而桩出来不平衡。

  3. 您将它分成不均组,启动,但扔掉所有的额外这将使它不均衡的。

您很少有超过RAND_MAX控制,而且它往往是一个素数反正。这确实只剩下2和3的可能性。

第三个选项看起来大致是这样的:
= {0};
    INT I;    对于(i = 0; I< MAX;我++)
        ++水桶[LIM(极限)];    //和打印一举超越什么*应该*生成
    对于(i = 0; I< LIMIT + 1;我++)
        的printf(%2D数:%d \\ n,我,水桶[I]);
}

于是,我们开始用数字从0到1009(1009是素数,所以它不会是我们选择的任何范围的整数倍)。于是,我们开始与1009的数字,并分成10桶。应在每个桶给100,9剩菜(这么说)得到吃掉由不要 / ,而循环。由于这是写现在,它分配并打印出一个额外的水桶。当我运行它,我得到完全100在每个桶0..9和0斗10.如果我注释掉不要 / 循环,我看到每个0..9 100,和9桶10。

只是可以肯定,我已经重新运行与其他各种数字为测试都产生的范围(主要用于素数),和水桶的数量。到目前为止,我还没有能够得到它的产生扭曲结果的范围(只要不要 / ,而循环被启用,当然)。

另外一个细节:有我用除法而不是其余部分该算法的原因。用)的好(甚至像样的)执行的兰特(这是无关紧要的,的的,当你钳使用分割数的范围,您保留的上方的输入位。当你与其余做到这一点,你保持的的输入位。碰巧的是,与典型的线性同余伪随机数发生器,下位往往比高位少随机的。合理的实现将抛出了一些最低显著位已经渲染此无关。而另一方面,也有兰特的一些pretty差实现周围,并用大多的,你最终得到质量更好用除法而不是其余的输出。

我也应该指出,有的那些大致相反的发电机 - 低位比高位更随意。至少在我的经验,这些都是非常罕见。这与高位更是随意的相当的更为常见。

I'd like to find an unskewed way of getting random numbers in C (although at most I'm going to be using it for values of 0-20, and more likely only 0-8). I've seen this formula but after running some tests I'm not sure if it's skewed or not. Any help?

Here is the full function used:

int randNum() 
{ 
    return 1 + (int) (10.0 * (rand() / (RAND_MAX + 1.0)));
}

I seeded it using:

unsigned int iseed = (unsigned int)time(NULL);
srand (iseed);

The one suggested below refuses to work for me I tried

int greek; 
for (j=0; j<50000; j++) 
{ 
greek =rand_lim(5); 
printf("%d, " greek); 
greek =(int) (NUM * (rand() / (RAND_MAX + 1.0))); 
int togo=number[greek]; 
number[greek]=togo+1; 
}

and it stops working and gives me the same number 50000 times when I comment out printf.

解决方案

Yes, it's skewed, unless your RAND_MAX happens to be a multiple of 10.

If you take the numbers from 0 to RAND_MAX, and try to divide them into 10 piles, you really have only three possibilities:

  1. RAND_MAX is a multiple of 10, and the piles come out even.
  2. RAND_MAX is not a multiple of 10, and the piles come out uneven.
  3. You split it into uneven groups to start with, but throw away all the "extras" that would make it uneven.

You rarely have control over RAND_MAX, and it's often a prime number anyway. That really only leaves 2 and 3 as possibilities.

The third option looks roughly like this: [Edit: After some thought, I've revised this to produce numbers in the range 0...(limit-1), to fit with the way most things in C and C++ work. This also simplifies the code (a tiny bit).

int rand_lim(int limit) {
/* return a random number in the range [0..limit)
 */

    int divisor = RAND_MAX/limit;
    int retval;

    do { 
        retval = rand() / divisor;
    } while (retval == limit);

    return retval;
}

For anybody who questions whether this method might leave some skew, I also wrote a rather different version, purely for testing. This one uses a decidedly non-random generator with a very limited range, so we can simply iterate through every number in the range. It looks like this:

#include <stdlib.h>
#include <stdio.h>

#define MAX 1009

int next_val() {
    // just return consecutive numbers
    static int v=0;

    return v++;
}

int lim(int limit) {
    int divisor = MAX/limit;
    int retval;

    do {
        retval = next_val() / divisor;
    } while (retval == limit);

    return retval;
}

#define LIMIT 10

int main() {

    // we'll allocate extra space at the end of the array:
    int buckets[LIMIT+2] = {0};
    int i;

    for (i=0; i<MAX; i++)
        ++buckets[lim(LIMIT)];

    // and print one beyond what *should* be generated
    for (i=0; i<LIMIT+1; i++)
        printf("%2d: %d\n", i, buckets[i]);
}

So, we're starting with numbers from 0 to 1009 (1009 is prime, so it won't be an exact multiple of any range we choose). So, we're starting with 1009 numbers, and splitting it into 10 buckets. That should give 100 in each bucket, and the 9 leftovers (so to speak) get "eaten" by the do/while loop. As it's written right now, it allocates and prints out an extra bucket. When I run it, I get exactly 100 in each of buckets 0..9, and 0 in bucket 10. If I comment out the do/while loop, I see 100 in each of 0..9, and 9 in bucket 10.

Just to be sure, I've re-run the test with various other numbers for both the range produced (mostly used prime numbers), and the number of buckets. So far, I haven't been able to get it to produce skewed results for any range (as long as the do/while loop is enabled, of course).

One other detail: there is a reason I used division instead of remainder in this algorithm. With a good (or even decent) implementation of rand() it's irrelevant, but when you clamp numbers to a range using division, you keep the upper bits of the input. When you do it with remainder, you keep the lower bits of the input. As it happens, with a typical linear congruential pseudo-random number generator, the lower bits tend to be less random than the upper bits. A reasonable implementation will throw out a number of the least significant bits already, rendering this irrelevant. On the other hand, there are some pretty poor implementations of rand around, and with most of them, you end up with better quality of output by using division rather than remainder.

I should also point out that there are generators that do roughly the opposite -- the lower bits are more random than the upper bits. At least in my experience, these are quite uncommon. That with which the upper bits are more random are considerably more common.

这篇关于难道&QUOT; N *(RAND()/ RAND_MAX)QUOT;使偏态随机数的分布?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆