<>背景

* 我非常喜欢编程语言,之前写过rust、R、python、C++等。
* 我的第一门语言就是R语言,然后在比较掌握R语言之后,又花了很长一段时间学习RCPP。
* 我觉得不管是会R还是说会python,都应该会C\C++。
* C\C++运行效率太顶了。牛!
<>主要内容

最近也刚好C之类的内容,这里就简单分享一个我遇到的非常有意思的内容:使用C和python两种编程语言、通过蒙特卡洛方法计算圆周率PI。

<>蒙特卡洛计算圆周率PI

蒙特卡洛计算圆周率PI其实是一个非常经典的案例,在R仿真里面,也都有。

基本上案例如下:

* 在一个边长为1的正方形里面,有一个半径为1/2的圆。
* 正方形和圆共一个中心点。圆内切正方形。
* 向这个正方形里面投点,计算点落在圆内的数量。落在圆内点的数量比上总点数就是等于 π / 4 \pi/4 π/4。
那么按照这个思想,只要是不断的生成若干个点,计算占比即可。

<>C代码

这里先分享一个C语言的代码:
#include <stdlib.h> #include <stdio.h> #include <chrono> #include <array>
#define N_POINTS 10000000 #define N_REPEATS 5 float estimate_pi(int n_points) {
double x, y, radius_squared, pi; int within_circle=0; for (int i=0; i <
n_points; i++) { x = (double)rand() / RAND_MAX; y = (double)rand() / RAND_MAX;
radius_squared = x*x + y*y; if (radius_squared <= 1) within_circle++; }
pi=(double)within_circle/N_POINTS * 4; return pi; } int main() { double
avg_time = 0; srand(42); for (int i=0; i < N_REPEATS; i++) { auto begin =
std::chrono::high_resolution_clock::now(); double pi = estimate_pi(N_POINTS);
auto end = std::chrono::high_resolution_clock::now(); auto elapsed =
std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin); avg_time +=
elapsed.count() * 1e-9; printf("Pi is approximately %g and took %.5f seconds to
calculate.\n", pi, elapsed.count() * 1e-9); } printf("\nEach loop took on
average %.5f seconds to calculate.\n", avg_time / N_REPEATS); }
这里在clion里面运行一下,可以看到非常的快,基本上都是在0.19秒左右。

<>python代码

既然c语言这么快,那python是什么情况,运行效率如何,这里给到python代码:
import random import time import argparse def estimate_pi( n_points: int,
show_estimate: bool, ) -> None: """ Simple Monte Carlo Pi estimation
calculation. Parameters ---------- n_points number of random numbers used to
for estimation. show_estimate if True, will show the estimation of Pi,
otherwise will not output anything. """ within_circle = 0 for _ in
range(n_points): x, y = (random.uniform(-1, 1) for v in range(2))
radius_squared = x**2 + y**2 if radius_squared <= 1: within_circle += 1
pi_estimate = 4 * within_circle / n_points if not show_estimate: print("Final
Estimation of Pi=", pi_estimate) def run_test( n_points: int, n_repeats: int,
only_time: bool, ) -> None: """ Perform the tests and measure required time.
Parameters ---------- n_points number of random numbers used to for estimation.
n_repeats number of times the test is repeated. only_time if True will only
print the time, otherwise will also show the Pi estimate and a neat formatted
time. """ start_time = time.time() for _ in range(n_repeats):
estimate_pi(n_points, only_time) if only_time: print(f"{(time.time() -
start_time)/n_repeats:.4f}") else: print( f"Estimating pi took {(time.time() -
start_time)/n_repeats:.4f} seconds per run." ) def positive_integer(value: str)
-> int: """Check for positive integer in arg_parse.""" int_value = int(value)
if int_value <= 0: raise argparse.ArgumentTypeError(f"{value} is an invalid
positive int value") return int_value def main(arguments=None): """Main loop in
arg parser.""" parser = argparse.ArgumentParser() parser.add_argument( "-p",
"--n_points", help="Number of random points to use for estimating Pi.",
type=positive_integer, default=1_000_000, ) parser.add_argument( "-r",
"--n_repeats", help="Number of times to repeat the calculation.",
type=positive_integer, default=5, ) parser.add_argument( "--only-time",
action='store_true', default=False, ) args = parser.parse_args() run_test(
args.n_points, args.n_repeats, args.only_time, ) if __name__ == "__main__":
main()
这里是python的运行结果,基本上在1.5秒左右

<>比较与总结

* 上面两个其实都不太公平,因为我的C语言代码是在WSL2里面运行的,cpu都是有损耗的情况下。跑出个0.19秒。
* 上面的python代码我是直接使用anaconda环境跑的。跑出个1.5秒左右。
* 基本上C语言的运行时间是python的10倍左右。
* 其实大家如果直接看上面的C代码,发现好像C语言代码也没那么难读。C语言的语法看着还挺现代的。
下图是各个版本的python和C语言的运行效率对比:C语言基本上是要比python快个10倍左右。

其实在科学计算领域,目前最火的就是python和C++。那如果真的是两个都会,确实就无敌了!

不多说了,我去学习C++了!

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信