【问题标题】:How to build a deterministic random plot如何构建确定性随机图
【发布时间】:2019-08-01 10:40:26
【问题描述】:

我有一个有趣的问题,一个简单但(显然)不容易的问题:

我的服务器正在提供包含 [-1,+1] 范围内的随机图的 JSON。每个值都与其对应的时间戳一起发送,这里是 JSON 的示例:

[
 { 1560765102, -0.53 },
 { 1560765103, -0.54 }, 
 { 1560765104, -0.43 }, 
 { 1560765105, -0.21 }, 
 { 1560765106, -0.11 }, 
 { 1560765107, 0.21 }, 
 { 1560765108, 0.34 }, 
 { 1560765109, 0.2 }, 
]

如您所见,该图不是直接从 PRNG 生成的(如 Math.rand()),否则它看起来像白色 AWGN 噪声。相反,每个点值都是前一个点的函数。这样,情节看起来更像是一个合理的随机温度信号,这就是我想要展示的。这是生成器:

var rndvalue = 0;
function random(timestamp)
{
    rndvalue += randomDet(timestamp) * 0.2 - 0.1;
    if(rndvalue > 1) rndvalue = 1;
    if(rndvalue < -1) rndvalue = -1;
    return rndvalue;
}

randomDet() 只不过是一个非常简单的哈希函数,它获取时间戳并在 [-1,+1] 范围内输出一个实数。信号被钳位到-1,+1。

客户端请求给定范围内的绘图,startTimestampendTimestamp,服务器只是循环遍历其间的所有时间戳并构建 JSON:

function getPlot(startTick, endTick)
{
    var points = [];
    var t = startTick;

    while(t < endTick)
    {
        var row = { tick: t, value: random(t) };
        points.push(row);
        t++;
    }

    return points;
}

问题是,每次客户端再次请求相同的时间戳间隔时,服务器都会返回不同的图(放大/缩小会令人困惑,因为图每次都会改变,而不是相应地重新缩放)。我希望情节具有确定性(即,如果请求相同的时间戳间隔,则始终相同)

我尝试了什么

我尝试修改 random() 函数的方式是,对于每个时间戳,它总是返回相同的点值。为此,我必须添加一个 for 循环并重新计算整个绘图,因为 timestamp = 0 直到请求的时间戳点值。它可以工作,但速度很慢,因为每个点值都是 O(N^2),其中 N 是请求的点时间戳。

var rndvalue = 0;
function random(tick)
{
    rndvalue = 0;
    for(var t = 0; t < tick; t++)
    {
        rndvalue += randomDet(t) * 0.2 - 0.1;
        if(rndvalue > 1) rndvalue = 1;
        if(rndvalue < -1) rndvalue = -1;
    }
    return rndvalue;
}

如何以更有效的方式完成?理想情况下 O(1)

【问题讨论】:

  • 只需srand(timestamp); 即可获得所需的每个随机数。
  • @pmg 不幸的是我的问题还不够清楚。如果你这样做,你不会得到一个确定的图,因为 rndvalue 变量是服务器的当前状态,每个点值都取决于它(因为每个点值是新随机值加上前一个值的总和(当前 rndvalue 值))
  • 您的randomDet 函数模拟了一些温度传感器输入。您可以考虑在读取一次后存储温度数据,而不是一次又一次地读取过去的传感器数据。
  • @Gerhardh 这可能是一个选项,但我需要将情节限制在给定的时间段内(即最短开始时间和最长结束时间)

标签: javascript node.js algorithm random


【解决方案1】:

您不会在每次调用getPlot() 时重置rndvalue 的值;因此,getPlot() 返回不同的结果,具体取决于调用该函数时rndvalue 的值。事实上,函数应该尽可能地自包含,而不是依赖于“全局”变量。以下解决方案直接使用randomDet(),避免使用“全局”变量。请注意,rndvalue 现在是 getPlot() 的局部变量。

function getPlot(startTick, endTick)
{
    var points = [];
    var rndvalue = 0;
    var t = startTick;

    while(t < endTick)
    {
        rndvalue += randomDet(t) * 0.2 - 0.1;
        if(rndvalue > 1) rndvalue = 1;
        if(rndvalue < -1) rndvalue = -1;
        var row = { tick: t, value: rndvalue };
        points.push(row);
        t++;
    }

    return points;
}

【讨论】:

    【解决方案2】:

    我通过用计算时间换取周期性图来“解决”了这个问题

    function random(tick)
    {
        var rndvalue = 0;
        for(var t = 0; t < (tick % 1000); t++)
        {
            rndvalue += randomDet(t) * 0.2 - 0.1;
            if(rndvalue > 1) rndvalue = 1;
            if(rndvalue < -1) rndvalue = -1;
        }
        return rndvalue;
    }
    

    这样,绘图是确定性的,只需要固定数量的 for 周期即可输出单个值。缺点是情节是周期性的,周期等于固定的for循环数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-07-20
      • 1970-01-01
      • 2013-12-24
      • 2015-12-24
      • 1970-01-01
      • 1970-01-01
      • 2018-05-20
      • 1970-01-01
      相关资源
      最近更新 更多