不正确的printf舍入或不精确的双倍?

时间:2016-09-29 16:14:09

标签: c pthreads printf double rounding

我使用多个pthreads来计算pi,使用在每个线程中运行的以下代码:

void *run(void *arg) {
  int *index = (int *) arg; // thread number, from 0 to thread_count - 1
  int i;
  double *partsum = (double *)malloc(sizeof(double));
  *partsum = 0.0;
  for (i = *index; i < NUM_STEPS; i += thread_count) {
    *partsum += 1.0 / (i * 4.0 + 1.0);
    *partsum -= 1.0 / (i * 4.0 + 3.0);
  }
  pthread_exit((void *) partsum);
}

然后将每个线程的返回值加到变量result并使用printf打印出来。如果我像这样使用printf,我会得到所需的输出(注意result存储在double中):

printf("%.10f\n", result);

此外,如果我改变线程数,结果不会改变。

奇怪的是,如果我像这样使用printf,结果将取决于正在运行的线程数。我使用的线程越多越准确。

printf("%.15f\n", result);

我想出了一些可能的原因:

  • 据我所知,如果小数点后需要超过15±2位,则不应该依赖printf输出值。但这仍然无法解释为什么最终值随线程数而变化。

  • 它可能与sizeof(void *)有关,但如果我使用的是32位机器,这只会导致问题(它根本不允许我将double转换为void *)。

我很清楚浮点数的机器表示,但我没有提供这种行为的可行解释。

为什么printf在使用不同的线程数时会输出不同的值?

这是主要的线程代码:

int main(int argc, char **argv) {

  int thread_count = atoi(argv[1]);
  pthread_t *threads = (pthread_t *) malloc(sizeof(pthread_t) * thread_count);
  int *args = (int *) malloc(sizeof(int) * thread_count);
  for (int i = 0; i < thread_count; i++)
  args[i] = i;

  for (int i = 0; i < thread_count; i++) {
    pthread_create(&threads[i], NULL, run, (void *) &args[i]); 
  }

  double result = 0.0;

  for (i = 0; i < thread_count; i++) {
    void **value = (void **)malloc(sizeof(double *));
    double **partsum;
    pthread_join(threads[i], value);

    partsum = (double **) value;
    result += **partsum;
    free(*partsum);
  }

  printf("%.15f\n", result);
}

0 个答案:

没有答案