【问题标题】:Function to generate randomly incrementing number over time随时间生成随机递增数字的函数
【发布时间】:2015-05-14 17:33:38
【问题描述】:

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

这是否可能不使用数据库或在任何地方存储计数器?

我的想法是检查自我的应用发布以来经过的秒数。然后只需将其放入一个计算出虚假下载计数的公式中即可。用户可以随时请求查看下载次数。

有没有随机递增的数学函数?我可以将我的secondsPassed 传递到那里并按我的意愿缩放它。

类似这样的:getDownloadCount(secondsPassed)

编辑:这是一个示例解决方案。但随着时间的推移,它的性能会变得更差。

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

【问题讨论】:

  • y = sin(x) + x 可能会做一些你正在寻找的事情。虽然不是真的随机。此外,除非您有编程问题,否则这不适合 stackoverflow。
  • 这不是一个完整的解决方案,但您可以以某种方式合并Prime-counting function π(x)
  • 为什么您认为数据库会有所帮助?所有计算机语言都有某种随机功能。您所要做的就是将累积的总数存储在一个变量中,也许是一个静态变量,然后将随机数添加到其中。但是我们需要更多的上下文。这甚至是一个编程问题吗?
  • 您使用什么语言?您可以不断地将随机数从 1..n 增加到变量。
  • 查看Poisson process

标签: math random


【解决方案1】:

制作虚假的下载计数听起来不是一件好事。然而,在设计安全通信协议时,有一些单调增长函数的合法用例,它们的值具有一定的随机性。

我假设你有:

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

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

找出当前时间在哪个窗口内。评估此窗口开始和结束处的参考函数。考虑由窗口的开始和结束时间给出的矩形以及参考函数给出的最小值和最大值。将这个矩形的角和你的常量种子输入 PRNG。使用 PRNG 在矩形内选择一个随机点。该点将位于最终曲线上。

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

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

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

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

【讨论】:

    【解决方案2】:

    您可以实现Morris Counter

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

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

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

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

    【讨论】:

      【解决方案3】:

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

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

      然后我们每次遍历相同的序列得到图。

      我们需要一个函数来增加我们的计数器,存储新的时间和计数并返回计数。

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

      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】:

        对于一些确定性函数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

        【讨论】:

        • 有时下载计数会因此而下降。如果我不断刷新计数,它看起来会很疯狂。
        【解决方案5】:

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

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

        【讨论】:

          【解决方案6】:

          您可以使用类似这样的快速解决方案(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(秒数)重播随机加法到计数器

          【讨论】:

            【解决方案7】:

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

            【讨论】:

              【解决方案8】:

              这是一个“假”下载计数器的 javascript 实现,对每个人来说都是一样的。这总是每次都为每个人返回相同的结果,并且不需要数据库或文件来执行此操作。它还可以优雅地处理您不同时请求新数据的情况,下次您请求一天时它仍然看起来很自然。 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>
              

              【讨论】:

                【解决方案9】:

                您可以使用 Unix 时间戳。比如:

                Downloads = constant + ( unix time / another constant ) 
                

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

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

                Downloads = (unix time) ^ constant
                

                等等。

                【讨论】:

                • 这太线性了
                • 我的错误。我编辑了答案。我的意思是使用 unix 时间作为变量。
                • 现在指数太高了 :p 下载量最终会变得太高
                猜你喜欢
                • 2018-03-28
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-12-20
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多