【问题标题】:How to randomize values between 1 and 10 for realistic ratings?如何随机化 1 到 10 之间的值以获得实际评级?
【发布时间】:2011-06-01 08:41:30
【问题描述】:

我有一个电影数据库,我需要在其中填充数据,以便更轻松地测试和开发应用程序。有表格来保存电影评分和用户帐户,用户对电影评分。

我已经开始开发一个脚本来使用虚假和通用数据填充数据库,但我不知道如何随机化评分。对于每部电影,我选择随机数量的用户,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 之间),然后创建一个评级的正态分布,其中所选点是最高的,这对我有用。

【问题讨论】:

  • 不太明白你的问题...你想从现有电影列表中随机选择收视率表吗?
  • 不,我想随机化看起来类似于上面图表的评分,以便我可以将它们插入数据库并使用一些数据。
  • 回声'9'; // 你不能证明它不是随机的
  • 我只是好奇:你关心这些数字有什么特别的原因吗?我想我只是生成测试数据,验证我的算法是否正确,而不是真正为数字“看起来”的样子出汗。
  • 这就是我正在做的“生成数据”。而且我不只是在谈论算法,我还必须设计网站,我希望有不同的参考,这样我就可以正确设计图表。这不是关于“数字是什么样子”,而是关于拥有某种“现实”数据而不是均匀分布,这没有多大帮助。

标签: php random numbers


【解决方案1】:

您想修正均值,可能还有方差,并围绕这些生成随机数。

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

编辑: 实际上,如果您考虑一下,这很容易解决:您的数字趋向于 5 的原因是因为您的规模在 1 和 10 之间(所以平均值是 5)。

只需取你的随机数,将它们全部加 8,然后将任何大于 10 的数字四舍五入到 10,你就会得到以 8-ish 为中心的东西(但在上面倾斜)。可能对您的目的足够好?

【讨论】:

  • 我不这么认为。数字趋向于 5,因为随机生成的数字是一致的,生成一个数字的概率对于每个其他数字都是完全相同的。全部加 8 并将大于 10 的数字四舍五入到 10 会给我一些稍微不同的结果,但每个评分都会有相似的票数。
【解决方案2】:

请记住,使用标准 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

似乎这个库非常适合您想要完成的工作。

【讨论】:

  • 所以我只需要类似的东西,但对于 PHP。 GaussionGenerator 可能就是我要找的。​​span>
  • @Nazgulled:The Math Uncommons 是开源软件,因此您可以将他们用于 GausianGenerator 的代码改编为 PHP。
【解决方案3】:

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

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

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

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

不错的 php 实现:D

【讨论】:

  • 仅 MersenneTwister 是不够的。他需要在生成中添加一些人为的分布。
【解决方案4】:

我的建议是你在随机数生成中涉及时间,还可以使用 mt_rand 之类的函数来改进随机数生成。尝试做一些复杂的浮点运算并转换为 int,最后应用 % max_value 以使结果符合您的限制。

例子:

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

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

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

【讨论】:

    【解决方案5】:

    正如 Kenny 所暗示的,您希望查看正态分布。如果您查看 IMDB 上的收视率,您会发现大多数电影都遵循正态分布。例外是最高和最低的排名。很多人会说他们讨厌或喜欢一部电影——他们夸大了自己的真实感受,因此出现了这些尖峰。因此,对于一组准确的数据,您需要将它们添加进去。也许让最低排名 =(接下来两个最低的总和)* 一个常数?

    【讨论】:

    • 我不需要真正准确的数据,我只是不希望所有电影都具有相似的分布(仅用于测试目的),以相同的平均值为中心。然后我会用 PHP 研究正态分布。
    【解决方案6】:

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

    想象一个数组,长度为 10 个元素,每个元素包含一个值 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,也许它是最新的僵尸 slasher 并且僵尸爱好者都投票了8,因为随着僵尸电影的上映,它非常好,而电影的其余部分公开投票给了 3,因为……总的来说,它更不那么糟糕)。

    【讨论】:

      猜你喜欢
      • 2018-09-14
      • 2018-05-14
      • 2016-04-23
      • 1970-01-01
      • 2014-03-06
      • 2016-02-10
      • 2013-04-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多