青羽的博客

恭喜你发现了一个不为人知的小岛

利用程序计算圆周率有很多方法,这里我们举四个小例子。


1. 统计方法

本质是随机撒点,也叫蒙特·卡罗法(Monte Carlo method)。

源代码:

1
2
3
4
5
6
7
8
9
10
11
12
void method_1(int N)
{
double x, y, hits = 0;
for (int i = 0; i < N; i++)
{
x = (double)rand() / RAND_MAX;
y = (double)rand() / RAND_MAX;
if (x * x + y * y < 1.0)
hits++;
}
printf("pi: %lf\n", (hits / N) * 4);
}

运行结果(N = 4000 * 4000):

这里的 time 是在 main() 函数中调用的计时功能,后面会介绍。

N 取这么小是因为这里只是一个demo,真正要计算圆周率的话不可能这么小的。


2. 统计方法

如果说蒙特卡罗法本质是随机撒点,那么这个本质就是均匀撒点。

源代码:

1
2
3
4
5
6
7
8
9
void method_2(int N)
{
double x, y, hits = 0;
for (x = 0; x < sqrt(N); x++)
for (y = 0; y < sqrt(N); y++)
if (x * x + y * y < N)
hits++;
printf("pi: %lf\n", (hits / N) * 4);
}

运行结果(N = 4000 * 4000):

虽然结果精确度和蒙特卡罗法差不多,但快了许多,因为蒙特卡罗法每次循环都要调用 rand() 函数来产生伪随机数(不引入特殊设备的话,计算机是无法产生真正的随机数的)。


3. 数学方法

数学是一个强有力的工具,利用级数展开的公式可以快速估算圆周率。

源代码:

1
2
3
4
5
6
7
void method_3(int I)
{
double pi = 0, k = 1;
for (int i = 0; i < I; i++, k = -k)
pi += k / (2 * i + 1);
printf("pi: %lf\n", pi * 4);
}

运行结果(I = 25):

因为数学方法和统计方法本质不一样,所以这里不再是循环次数 N 而是迭代次数 I (iteration)。


4. 数学方法

上面那个公式效果似乎不尽人意。当然我们可以增加迭代次数,但是否有收敛更快的公式呢?看看下面这个怎么样:

源代码:

1
2
3
4
5
6
7
8
9
10
void method_4(int I)
{
double pi = 1, n = 1;
for (int i = 1; i < I; i++)
{
n *= (double)i / (2 * i + 1);
pi += n;
}
printf("pi: %lf\n", pi * 2);
}

运行结果(I = 25):

Nice!

可以看到,仅仅25次迭代,就有如此高的精度,且耗费时间小于0.01秒,很不错呢。


对了,关于计时,其实很简单:

1
2
3
4
5
6
7
8
9
10
clock_t start, end;

start = clock();
// method_1(N);
// method_2(N);
// method_3(I);
method_4(I);
end = clock();

printf("time: %.2lf s\n", (double)(end - start) / CLOCKS_PER_SEC);

clock_t 类型和 clock() 函数在 time.h 头文件中,clock() 调用一次即记录此时的程序已运行时间,两次调用做差,即得中间过程的运行耗时。

想查看完整的代码请访问我的 GitHub


这是我自己在实践中总结的一套优化Windows系统的流程,按流程走一次就够了。适用于Windows 10。

首先,下载一个很小的工具包:Windows优化,然后按照下列步骤操作:

  1. 设置->应用->应用和功能->卸载多余应用、功能
  2. 卸载预装应用->Uninstall
  3. 回收站->属性->每个盘:直接删除,显示删除确认对话框
  4. 快速访问->选项->Win+E打开此电脑、去掉隐私项
  5. 删除此电脑那七个文件夹->/WindowsRegistry.reg
  6. 设置->系统->关于->重命名这台电脑
  7. 优化右键菜单->/RightMenuMgr/RightMenuMgr.exe
  8. Windows管理工具->磁盘清理->以管理员模式清理系统盘
  9. 安装CCleaner->快速清理、注册表清理->卸载CCleaner

另外:

  • 如果是笔记本电脑可以:设置->系统->电源和睡眠->其他电源设置->关闭盖子时不采取任何操作,防止一不小心合上盖子休眠导致一些进程被kill。
  • 建议:桌面在开机后和关机前都没有任何图标(“此电脑”用Win+E打开,“回收站”不用),原因无他,好看而已(前提是有一张好看的壁纸)。

Uninstall

管理员模式打开PowerShell,复制所需命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 应用商店:
Get-AppxPackage *WindowsStore* | Remove-AppxPackage

# OneNote:
Get-AppxPackage *OneNote* | Remove-AppxPackage

# 3D:
Get-AppxPackage *3d* | Remove-AppxPackage

# Camera相机:
Get-AppxPackage *camera* | Remove-AppxPackage

# 邮件和日历:
Get-AppxPackage *communi* | Remove-AppxPackage

# 新闻订阅:
Get-AppxPackage *bing* | Remove-AppxPackage

# Groove音乐、电影与电视:
Get-AppxPackage *zune* | Remove-AppxPackage

# 人脉:
Get-AppxPackage *people* | Remove-AppxPackage

# 手机伴侣:
Get-AppxPackage *phone* | Remove-AppxPackage

# 纸牌游戏:
Get-AppxPackage *solit* | Remove-AppxPackage

# 录音机:
Get-AppxPackage *soundrec* | Remove-AppxPackage

# Xbox:
Get-AppxPackage *xbox* | Remove-AppxPackage

解释一下原理:Get-AppxPackage是一条命令,后面接参数。*是通配符,能匹配任意字符串,因而*WindowsStore*表示含有WindowsStore的任意字符串,作为命令的参数。其他同理。由前一个命令得到的标准输出通过管道符|转换为标准输入传给Remove-AppxPackage这个命令进行卸载操作。