【问题标题】:How to get equal number of elements after range division leaving a remainder如何在范围划分后获得相等数量的元素留下余数
【发布时间】:2019-03-24 17:02:50
【问题描述】:

我知道标题不是最好的描述,但它是我能做到的最好的。
长故事排序,我正在尝试获取一系列数字, 让我们举个例子:

最小值:0 和最大值:10 , 所以范围是 10 。

我想将范围划分为 n 个字段(用户提供此输入,因此它是可变的),然后使用 fork() 创建 n 个线程子项,其中每个线程将获得这些数字的自己的子范围并执行一些使用这些数字的代码,实际上它会检查这个数字是否是质数。
所以我的问题是我想不出一个公式来让数字平分。

我试过了:

    for(int i = 0; i<n; i++){
        //fork()
        int temp = MIN + (i*(RANGE/n));
        for(int a =; a< temp +(RANGE/n)+1; a++){
            //check if prime
            //other actions
         }
     }

但我知道这将无法正常工作,因为如果我们有 3 个线程 (n),它将检查范围 (0,3)、(3,6)、(6,9),因为

(RANGE/n) 给出 3

这意味着最后一个数字(在本例中为 10)将永远不会被检查,以防 RANGE 与 N 个子节点的除法留下余数。
有没有什么聪明的方法可以分割范围并每次通过不同数量的进程检查所有数字?
提前致谢

【问题讨论】:

    标签: c multithreading formula division


    【解决方案1】:

    范围除法后如何获得相等数量的元素

    各种方法。

    一个关键问题是010 是否都包含在整数范围内:是[0... 10] 还是[0... 10) 还是...?注意])?让我们假设包含列表端点,[0... 10] 是 11 个不同的整数值。

    注意:有11个数字分成12组等极端情况。

    下面从范围的第一个1/n 部分形成子范围,然后是剩余范围的1/(n-1) 部分,等等。

    void range(int n, int inclusive_min, int inclusive_max) {
      printf("Range [%d %d] / %d\n", inclusive_min, inclusive_max, n);
      for(int i = n; i > 0 && inclusive_min <= inclusive_max; i--) {
        int range = 1 + inclusive_max - inclusive_min;
        int sub_range = range/i;
        if (sub_range == 0) sub_range = 1;
        printf("Sub range [%d %d]\n", inclusive_min, inclusive_min + sub_range - 1);
        inclusive_min += sub_range;
      }
    }
    
    int main(void) {
      range(3, 0, 10);
      range(2, 0, 10);
      range(5, 0, 10);
      range(3, 0, 1);
      return 0;
    }
    

    输出

    Range [0 10] / 3
    Sub range [0 2]
    Sub range [3 6]
    Sub range [7 10]
    Range [0 10] / 2
    Sub range [0 4]
    Sub range [5 10]
    Range [0 10] / 5
    Sub range [0 1]
    Sub range [2 3]
    Sub range [4 5]
    Sub range [6 7]
    Sub range [8 10]
    Range [0 1] / 3
    Sub range [0 0]
    Sub range [1 1]
    

    更优雅的解决方案,类似于Bresenham's line algorithm

    void range(int n, int inclusive_min, int inclusive_max) {
      printf("Range [%d %d] / %d\n", inclusive_min, inclusive_max, n);
      int range = 1 + inclusive_max - inclusive_min;
      int sub_range = range / n;
      int sub_range_res = range % n;
      int p = 0;
      for (int i = 0; i < n; i++) {
        int next = inclusive_min + sub_range;
        p += sub_range_res;
        if (2 * p >= n) {  // like p >= n/2 without integer truncation.
          p -= n;
          next++;
        }
        if (next > inclusive_min) {
          printf("Sub range %d:[%d %d]\n", i, inclusive_min, next - 1);
        }
        inclusive_min = next;
      }
    }
    

    输出

    Range [0 10] / 3
    Sub range 0:[0 3]
    Sub range 1:[4 6]
    Sub range 2:[7 10]
    Range [0 10] / 2
    Sub range 0:[0 5]
    Sub range 1:[6 10]
    Range [0 10] / 5
    Sub range 0:[0 1]
    Sub range 1:[2 3]
    Sub range 2:[4 6]
    Sub range 3:[7 8]
    Sub range 4:[9 10]
    Range [0 1] / 3
    Sub range 0:[0 0]
    Sub range 2:[1 1]
    

    【讨论】:

      【解决方案2】:

      如果您的任务是验证一个数是否为素数,则将较大的数字放在较小的组中会很方便(因为验证它们是否为素数更困难)。

      您可以使用由 MAX 启动的策略。然后创建以下间隔:例如 {MAX-1, MAX-2}(依此类推),直到您拥有所需范围的数量。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-21
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多