随时间生成随机递增数的函数

时间:2015-05-14 17:33:39

标签: math random

我正在尝试伪造download count。它应随着时间的推移随机增加。一些类似下载计数的模式会很好。

这可以不使用数据库,或在任何地方存储计数器吗?

我的想法是检查自我的应用发布以来经过的秒数。然后把它扔进一个吐出伪造下载计数的公式中。用户可以随时请求查看下载计数。

是否有随机增量的数学函数?我可以将secondsPassed传递到那里并按照我想要的方式进行缩放。

这样的事情:getDownloadCount(secondsPassed)

enter image description here

编辑:这是一个示例解决方案。但随着时间的推移,它会有更糟糕的表现。

downloadCount = 0
loop secondsPassed/60 times // Loop one more time for every minute passed
  downloadCount += seededRandom(0, 10)

9 个答案:

答案 0 :(得分:1)

伪造下载次数并不是一件好事。然而,在设计安全通信协议时,有单调增长函数的合法用例,其值有一些随机性。

我假设你有:

  • 作为单调增长函数给出的增长模型,提供所需函数的近似值。
  • 访问永不减少的时间戳。
  • 能够存储常量随机种子以及函数定义。
  • 无法在查询的函数上存储任何更新的数据。

首先你决定一个窗口长度,它将控制最终输出中的随机性。我希望你能希望这个大约一个小时或几个小时。

确定当前时间在哪个窗口。在此窗口的开头和结尾评估参考函数。考虑窗口的开始和结束时间给出的矩形以及参考函数给出的最小值和最大值。将此矩形的角和恒定种子送入PRNG。使用PRNG选择矩形内的随机点。这一点将在最后的曲线上。

对其中一个邻居窗口执行相同的计算。使用哪个邻居窗口取决于曲线上的第一个计算点是在当前时间的左侧还是右侧。

现在您在曲线上有两个点(可重复且一致),您将不得不重复以下过程。

最终曲线上给出了两点。考虑那些角落给出的矩形。将角落和恒定的种子喂入PRNG。使用该PRNG选择矩形内的随机点。这一点将在最后的曲线上。丢弃一个不再需要的外部点。

由于Y值被限制为整数,一旦曲线上的两个点具有相同的Y坐标,此过程最终将终止,并且您将知道该函数必须在这两个点之间保持不变。

答案 1 :(得分:1)

您可以实施Morris Counter

它的工作方式如下:首先将计数器设置为1.每次要增加计数(可能是某个循环的每次迭代或每次事件发生时,但不需要随机确定) ,然后你做一个随机的程序来确定它对柜台的影响。

它可能没有效果,或者它可以具有提高计数量级的效果。该概率基于n个连续的公平硬币是否翻转所有翻转头,其中n是以二进制编码当前计数器值所需的比特数。结果,一旦计数器变得非常高,就很难让它变得更高(计数器的状态模拟了一种现象,你已经高估了计数,所以现在你需要很多没有事情发生的事件补偿,使计数更准确)。

这是一种便宜的方式来存储非常大的集合的大致数量,但是没有理由不能将它用作随机增加的计数器设备。

如果您想要更高的准确度,或者您希望计数输出更多是“正常”数字而不是总是2的幂,那么您可以创建几个Morris计数器,并在每个步骤中平均计算当前计数的集合他们都是。

答案 2 :(得分:0)

对于某些确定性函数f,(可能是f(x) = x,或者你的假应用程序真的很棒f(x) = 2^x),以及随机函数r输出随机数有时是消极的,有时是积极的。

您的图表功能g可以是:

g(x) = f(x) + r

修改

这个怎么样:https://gamedev.stackexchange.com/questions/26391/is-there-a-family-of-monotonically-non-decreasing-noise-functions

答案 3 :(得分:0)

您所追随的序列总是随机增加,具体取决于您上次请求序列的时间。

这可以通过始终播种相同的随机序列来完成。

然后我们每次迭代相同的序列以获得图形。

我们需要一个递增计数器的函数,存储新的Time和Count并返回计数。

理想情况下,我们会将增量建模为泊松过程,但这里将采用线性过程。

class Counter {
    private static int counter = 0;
    private static int time = 0;

    private static double rate = 5.0;

    private Random r;

    public Counter(int seed){
        counter = 0;
        r = new Random(seed);
    }

    private int poisson(double rate, int diff){
    // We're gonna cheat here and sample uniformly
        return r.Next(0, (int)Math.Round(rate * diff));
    }

    public int getNext(int t){
        var diff = t - time;
        time = t;
        if (diff <= 0) return counter;

        counter += this.poisson(rate, diff);
        return counter;
    }
}
void Main()
{
    var c = new Counter(1024);
    for(var i = 0; i< 10; i++){
        Console.WriteLine(String.Format("||{0}\t|{1}\t||",i,c.getNext(i)));
    }
}

此输出(例如):

||t  |hit||
||0  |0  ||
||1  |3  ||
||2  |4  ||
||3  |6  ||
||4  |6  ||
||5  |8  ||
||6  |10  ||
||7  |13  ||
||8  |13  ||
||9  |16  ||

答案 4 :(得分:0)

嗯,它不是“随机”,但您可以使用A*(X/B + SIN(X/B))(按某些数字缩放)来引入一些噪音。您可以调整A和B来更改结果的比例以及“噪音”循环的频率。

实际上,任何在某些范围内具有一阶导数的周期函数都可以工作。

答案 5 :(得分:0)

作为快速解决方案,您可以使用类似这样的东西(java中的代码):

static long f(final int x) {
    long r = 0; // initial counter
    long n = 36969L; // seed
    for (int i = 0; i <= x; i++) {
        n = 69069L * n + 1234567L; // generate Ith random number
        r += (n & 0xf); // add random number to counter
    }
    return r;
}

通过使用数字36969L0xf,您可以获得不同的结果

数字69069L1234567L来自标准LCG

主要思想 - 创建简单随机,使用相同的种子和每次传递的x(秒数)重播随机添加到计数器

答案 6 :(得分:0)

下载等随机事件的一个好模型是泊松分布。您需要估计给定时间段内的平均下载次数(例如小时),然后反转泊松分布以获得给定均匀分布的随机数的时间段内的下载次数。为了获得额外的真实感,您可以根据一天中的时间,一周中的时间等来改变平均值。样本算法可以在http://en.m.wikipedia.org/wiki/Poisson_distribution#Generating_Poisson-distributed_random_variables获得。

答案 7 :(得分:0)

这是一个“虚假”下载计数器的javascript实现,对每个人来说都是一样的。这始终为每个人返回相同的结果,并且不需要数据库或文件来执行此操作。它还可以优雅地处理您不同时请求新数据的情况,下次您请求一天时它仍然看起来很自然。 enter image description here https://jsfiddle.net/Lru1tenL/1/

Counter = {
        time:Date.now(),
        count:0,
        rate:0.45
    };

Counter.seed = function(seed, startTime)
{
    this.time = startTime,
    this.count = 0,
    this.prng = new Math.seedrandom(seed);
    this.prng.getRandomInt = function(min, max) {
      return Math.floor(this() * (max - min)) + min;
    };
};

Counter.getNext = function(t){

    var diff = t - this.time;
    console.log(diff);


    if(diff <= 0) return this.count;

    this.time = t;
    var max = Math.ceil(diff/100 * this.rate);

    console.log("max: " + max);
    this.count += this.prng.getRandomInt(0,max);
    return this.count;
};

var results = [];

var today = Date.now();

Counter.seed("My Random Seed", today);


for (var i = 0; i < 7; i++) {
    if(i === 4)
    {
        results.push(null);
    } else {
        var future = today +  86400000 * i;
        results.push(Counter.getNext(future));
    }
}

console.log(results);

    var data = {
    labels: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday","Sunday"],
    datasets: [
        {
            label: "My Second dataset",
            fillColor: "rgba(151,187,205,0.2)",
            strokeColor: "rgba(151,187,205,1)",
            pointColor: "rgba(151,187,205,1)",
            pointStrokeColor: "#fff",
            pointHighlightFill: "#fff",
            pointHighlightStroke: "rgba(151,187,205,1)",
            data: results
        }

    ]
};

var ctx = document.getElementById("myChart").getContext("2d");
var myLineChart = new Chart(ctx).Line(data);

是javascript。它创建一个计数器对象,根据请求的上一个值的时间在请求时递增。可重复性来自第三方库“seedrandom”,图表使用chartjs绘制。

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/seedrandom/2.4.0/seedrandom.min.js">
</script>
<body>
    <canvas id="myChart" width="600" height="400"></canvas>

</body>
</html>

答案 8 :(得分:-1)

您可以使用Unix时间戳。类似的东西:

Downloads = constant + ( unix time / another constant ) 

您可以改变两个常数以获得合理的数字。

P.S:如果你想要一个线性函数,那就是你可以这样做:

Downloads = (unix time) ^ constant

等等。