1.题目要求
使用2个线程根据莱布尼兹级数计算PI
- 莱布尼兹级数公式: 1 - 1/3 + 1/5 - 1/7 + 1/9 - … = PI/4
- 主线程创建1个辅助线程
- 主线程计算级数的前半部分
- 辅助线程计算级数的后半部分
- 主线程等待辅助线程运行结束后,将前半部分和后半部分相加
2.解决思路
按照题目要求,首先需要实现主线程master
和辅助线程work
,二者分别用于计算莱布尼兹级数的前半部分和后半部分,莱布尼兹级数公式中有无穷项,需要定义程序中计算的项数N
,比如设定为5000
,在线程函数中功能的实现方法相同,只是计算的起止范围不同,master
计算从第1
到N/2
项,work
计算从第N/2+1
到N
项。在for
循环中,每一项的分子均为1,分母为i*2-1
,其符号根据i
是否能整除2决定,观察级数可得若能整除则符号为负,否则符号为正,定义两个double
型全局变量用于存储计算结果。
在main函数中,主线程创建一个辅助线程,辅助工作线程执行worker
函数,主线程执行master
函数,在主线程中使用pthread_join
, 等待子线程运行结束,主线程将master_output
和worker_output
汇总存储到变量total
,需要计算的PI值根据公式为total
的4倍,打印输出结果即可。
3.代码
#include <stdio.h>
#include <pthread.h>
#define N 100000
double worker_output = 0;
double master_output = 0;
// 主线程计算级数的前半部分
void master() {
int i, j;
for(i = 1; i <= N / 2; i++) {
j = 2 * i - 1;
if(i % 2 == 0) {
j = -j;
}
master_output += (double) 1 / j;
}
}
// 辅助线程计算级数的后半部分
void *worker(void *arg) {
int i, j;
for(i = N / 2 + 1; i <= N; i++) {
j = 2 * i - 1;
if(i % 2 == 0) {
j = -j;
}
worker_output += (double) 1 / j;
}
return NULL;
}
int main() {
pthread_t worker_tid;
double total, PI;
pthread_create(&worker_tid, NULL, worker, NULL);
master();
pthread_join(worker_tid, NULL);
total = worker_output + master_output;
PI = 4 * total;
printf("compute times = %d\n", N);
printf("master_output = %lf, worker_output = %lf, total = %lf\n", master_output, worker_output, total);
printf("PI = %lf\n", PI);
return 0;
}
4.运行结果
$ gcc pi1.c -lpthread
$ ./a.out
compute times = 100000
master_output = 0.785393, worker_output = 0.000002, total = 0.785396
PI = 3.141583