【问题标题】:Weighted probability with long doubles长双打的加权概率
【发布时间】:2013-02-18 13:31:43
【问题描述】:

我正在使用 C++ 中包含大约 2000 个元素的数组。

每个元素代表该元素被随机选择的概率。

然后我将此数组转换为累积数组,目的是使用它来计算掷骰子时选择哪个元素。

示例数组: {1,2,3,4,5}

示例累积数组: {1,3,6,10,15}

当数字 3、4 或 5 滚动时,我希望能够在累积数组中选择 3。

增加的复杂性是我的数组由长双精度数组成。以下是几个连续元素的示例:

0.96930161525189592646367317541056252139242133125662803649902343750 0.96941377254127855667142910078837303444743156433105468750000000000 0.96944321382974149711383993199831365927821025252342224121093750000 0.96946143938926617454089618153290075497352518141269683837890625000 0.96950069444055009509463721739663810694764833897352218627929687500 0.96951751803395748961766908990966840065084397792816162109375000000

这可能是对这个数据集进行加权概率的一种糟糕的方法,所以我愿意接受任何关于解决这个问题的更好方法的建议。

【问题讨论】:

  • 为什么需要这么长的号码?
  • 我不太会解释,所以这里有一个简化的例子 {Item1 - 100, Item2 - 200} 我需要知道 Item1 出现了 100/300 次。碰巧的是,对于我的 2000 个项目,这些值产生了像上面这样的概率。我想保持尽可能精确,因为降低概率可能会对我的最终值产生负面影响(即 Item1 永远不会出现)。
  • partial_sum
  • std::upper_bound... 从结果中减去 1 以获得“至少等于”参数的元素。
  • boost 有一个 RNG 就是为了这个目的

标签: c++ vector probability long-double


【解决方案1】:

你可以使用partial_sum:

unsigned int SIZE = 5;
int array[SIZE] = {1,2,3,4,5};
int partials[SIZE] = {0};

partial_sum(array, array+SIZE, partials);
// partials is now {1,3,6,10,15}

您想要的数组值可从部分和中获得:

12 == array[2] + array[3] + array[4];

12 == partials[4] - partials[1];

总和显然是部分和中的最后一个值:

15 == partial[4];

【讨论】:

    【解决方案2】:

    考虑将信息存储为整数分子和分母,以便在最后一步之前不会损失精度。

    【讨论】:

      【解决方案3】:

      您实际上可以使用流选择来执行此操作,而无需计算部分和数组。这是我用 Java 编写的代码:

      public static int selectRandomWeighted(double[] wts, Random rnd) {
          int selected = 0;
          double total = wts[0];
      
          for( int i = 1; i < wts.length; i++ ) {
              total += wts[i];
      
              if( rnd.nextDouble() <= (wts[i] / total)) {
                  selected = i;
              }
          }
      
          return selected;        
      }
      

      如果您想在总和中保留尽可能多的精度,则可以使用Kahan summation 进一步改进上述内容。

      但是,如果你想重复从这个数组中提取,那么预先计算一个部分和的数组并使用二进制搜索来找到正确的索引会更快。

      【讨论】:

        【解决方案4】:

        好的,我想我已经解决了这个问题。

        我只是做了一个二分搜索,但不是只有

        if (arr[middle] == value)
        

        我在 OR 中添加了

        if (arr[middle] == value || (arr[middle] < value && arr[middle+1] > value))
        

        这似乎以我希望的方式处理它。

        【讨论】:

        • 如果数组中只有1值怎么办?
        • 数组中至少有 1000 个项目。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-08
        相关资源
        最近更新 更多