如何将1到10之间的值随机化以获得真实的评级?

时间:2010-12-30 02:04:34

标签: php random numbers

我有一个电影数据库,我需要填充数据,以便更容易测试和开发应用程序。有用于保存电影评级和用户帐户的表格,用户评价电影。

我已经开始开发一个脚本,用虚假和通用数据填充数据库,但我不知道如何随机化评级。对于每部电影,我选择随机数量的用户,100,500,1000,等等。并且对于每个用户,我将评级从1到10随机化。但是这些评级导致相同的平均值,大约为5.这意味着特定电影的评级(1到10)的分布基本相同。这根本不是“现实的”,因为所有像这样生成的评级的电影都会有相同的平均值,因此来自不同用户和不同用户数量的相同评级并不重要。

我希望电影A平均为7,电影B平均为5,电影C平均为8等等......但我不希望每部电影的平均值不同。我的意思是,产生这样的评级(对于特定数量的用户)会很好: http://www.imdb.com/title/tt1046173/ratings或此http://www.imdb.com/title/tt0486640/ratings

你知道,随机的东西会产生两种不同的变化,如上所述。我点击刷新,我得到第一个图表,我点击刷新并得到第二个,再次点击并获得不同或类似的东西,“随机”和“现实”。

我也将在我的应用程序上显示这样的图形,所以有不同的发行版看起来很不错。但我不知道如何通过一个简单的脚本随机完成这一任务。

我该如何解决这个问题?也许这太多的工作不值得了?

也许更简单的事情,比如选择一个点(1到10之间),然后创建一个正常的评级分布,其中所选择的点是最高点,这对我有用。

6 个答案:

答案 0 :(得分:4)

你想要修正均值,可能还有方差,然后围绕这些来产生随机数。

这应该可以帮助您入门: Generating random numbers with known mean and variance

编辑: 实际上,如果你考虑一下,这可以很容易地解决:你的数字倾向于5的原因是因为你的比例在1到10之间(所以平均值是5)。

只需取随机数字,对所有数字加8,然后将任何大于10的数字舍入为10,你将得到一些以8-ish为中心的东西(但偏向上方)。可能对你的目的足够好吗?

答案 1 :(得分:3)

请记住,使用标准RNG(随机数生成器),您将获得非常均匀的值分布。正如您所发现的那样,给定足够的“随机”值可以获得平均结果。对于数据库的人口,我会考虑这种方法:

选择一个随机数作为电影的平均分数。然后,在该平均值的上限生成一组随机数。例如,如果你随机生成一个7,则生成5到9之间的随机数。然后输入1到6和8到10之间的几个值,以显示异常值。

编辑:

这个answer可能就是你要找的,用Java编写代码。

均匀分布示例:

您的代码可能类似于以下内容:

public class EvenDistribution
{
    private static Random random = new Random();

    public static void main(String[] args)
    {
        int maxValue = 20;

        int[] distribution = new int[maxValue];

        int iterations = 1000;

        for (int i = 0; i < iterations; i++)
        {
            int rand = random.nextInt(maxValue);
            distribution[rand]++;
        }

        for (int i = 0; i < distribution.length; i++)
        {
            System.out.println(i+1+": "+distribution[i]);
        }
    }
}

此类具有以下输出:

  

1:47
2:45
3:59
4:   52
5:54
6:52
7:49
  8:49
9:49章10:48
11:   40
12:43
13:42
14:   61
15:43
16:55
17:   47
18:55
19:64
20:   46个

分布非常均匀。 19看起来有点异常,但总的来说我们可以说这种RNG方法产生了可预测的结果。

使用上面提到的Math Uncommons库,我使用类似的代码,使用GaussianGenerator

public class RandomDistribution {
    private static MersenneTwisterRNG random = new MersenneTwisterRNG();
    private static GaussianGenerator gen = new GaussianGenerator(7, 3, random);

    public static void main(String[] args)
    {
        int maxValue = 20;

        int[] distribution = new int[maxValue];

        int iterations = 1000;

        for (int i = 0; i < iterations; i++)
        {
            int rand = Math.abs(gen.nextValue().intValue());
            distribution[rand]++;
        }

        for (int i = 0; i < distribution.length; i++)
        {
            System.out.println(i+1+": "+distribution[i]);
        }
    }
}

它产生了以下输出:

1:19
2:27
3:41
4:68
5:110
6:111
7:125
8:138
9:125
10:85
11:64
12:32
13:32
14:14
15:5
16:2
17:1
18:0
19:1
20:0

似乎这个库对你想要完成的事情非常有用。

答案 2 :(得分:1)

尝试使用Mersenne Twister算法获得高质量的随机数。

http://en.wikipedia.org/wiki/Mersenne_twister

我认为这些坏人有一些php实现:

http://www.phpdig.net/ref/rn35re672.html

很好的PHP实现:D

答案 3 :(得分:0)

我的目的是在randon数生成中涉及时间,也使用mt_rand等函数来改善随机生成。尝试做一些复杂的浮点运算和转换为int,最后应用%max_value,以便结果符合你的限制。

示例:

function x()
{
 return (time() * 7.3333333333 * mt_rand(0.1 , 10.1));
}

$rank = (x() + 3.99999) % 10);

我不是说这有效,但是说明了这个想法。希望它有所帮助!

答案 4 :(得分:0)

正如Kenny暗示的那样,您想要查看正态分布。如果你看看IMDB上的收视率,你会发现大多数电影都遵循正常的分布。最高和最低排名是例外。很多人会说他们讨厌或喜欢一部电影 - 他们夸大了他们的真实感受,因此这些飙升。因此,对于准确的数据集,您需要添加这些数据。或许让最低排名=(下两个最低的总和)*一个常数?

答案 5 :(得分:0)

我也支持Kenny的建议,但是想补充说明实施。虽然这不是我见过的最好的方法,但由于它很容易实现了几次。

想象一个数组十个元素,每个元素包含一个值10.如果你要生成1到100之间的随机数,你可以计入数组,将每个元素推进到数组中的下一个索引,如果值为到此为止,大于数组值的总和。通过这种方式,您可以将1-100映射到1-10。

虽然上面对这种技术的使用很糟糕,你可以很容易地看到你如何通过一点点创造力来创造你自己的非均匀分布。例如,考虑:

1,2,4,8,16,16,8,4,2,1

以上10个元素总和为64,因此非常适合映射64到10(这只是一个例子)。我见过的实现总是将分布总和加到一个特定的数字,但是如果你封装从1-10得到一个随机数,那么你可以得到不同总和的分布。

通过仅创建一些此类分布,您可以通过对概率向量求和来创建许多合理分布(考虑高度本地化的分布在3左右,分布高度本地化在8左右,也许是最新的僵尸砍刀和僵尸爱好者全部投票8因为当僵尸电影去了它是相当不错的,电影的其余部分上市投票3,因为......总的来说,它更少被吸引。