展开全部

因为在Mathematica中使用循环确实是低效的。32313133353236313431303231363533e78988e69d8331333361313961。。。。。

深层次的原因涉及到Mathematica的底层实现所以我不太懂,但是至少从下面几个例子可以看出Mathematica里确实有很多比循环更好的方法

求和

首先举一个最简单的求和例子,求的值。为了测试运行时间取n=10^6

一个刚接触Mathematica的同学多半会这样写

sum = 0;

For[i = 1, i <= 10^6, i++,

sum += Sin[N@i]];

(*其中N@i的作用是把整数i转化为浮点数,类似于C里的double*)

sum

为了便于计时用Module封装一下,运行时间是2.13秒,如下图

然后一个有一定Mathematica经验的同学多半会知道同样作为循环的Do速度比For快,于是他可能会这么写

然后一个有一定Mathematica经验的同学多半会知道同样作为循环的Do速度比For快,于是他可能会这么写

sum = 0;

Do[sum += Sin[N@i], {i, 1, 10^6}];

sum

如下图,用时1.37秒,比For快了不少

当然了知道Do速度比For快的同学不太可能不知道Sum函数,所以上面其实是我口胡的,他应该会这么写

Sum[Sin[N@i], {i, 1, 10^6}]

如下图,同样的结果,只用了不到0.06秒

如果这位同学还知道Listable属性并且电脑内存不算太小的话,他也可能会这么写

Tr@Sin[N@Range[10^6]]

如下图,只用了不到0.02秒,速度超过For循环的100倍

当然了这只是一个最简单的例子,而且如果数据量更大的话最后一种方法就不能用了。但是这也足以说明在求和时用循环是低效的,无论是内置的Sum函数还是向量化运算,在效率上都远远高于循环

(这部分模仿了不同程序员如何编写阶乘函数这篇文章,强烈推荐对Mathematica有兴趣的同学去看看)

迭代

接下来举一个迭代的例子,(即Logistic map),取,为了测试运行时间同样取n=10^6

还是先用For循环的做法

x = 0.5;

For[i = 1, i <= 10^6, i++,

x = 3.5 x (1 - x);

];

x

如下图,运行时间2.06秒

(Do循环和For类似,篇幅所限这里就不写了,有兴趣的同学可以自行尝试)

(Do循环和For类似,篇幅所限这里就不写了,有兴趣的同学可以自行尝试)

然后看看内置的Nest函数

Nest[3.5 # (1 - #) &, 0.5, 10^6]

如下图,用时0.02秒,又是将近两个数量级的效率差异

当然了Nest的使用涉及到纯函数,对于Mathematica初学者来说可能有些难以理解,而且一些比较复杂的迭代不太容易写成Nest的形式,但是在迭代时Nest(还包括Fold)的效率确实要好于循环

当然了Nest的使用涉及到纯函数,对于Mathematica初学者来说可能有些难以理解,而且一些比较复杂的迭代不太容易写成Nest的形式,但是在迭代时Nest(还包括Fold)的效率确实要好于循环

遍历列表

依然举一个简单的例子:求一个列表中偶数的个数。为测试生成10^6个1到10之间的随机整数

list = RandomInteger[{1, 10}, 10^6];

(*生成10^6个随机整数*)

如果用For循环的话代码是这样的

num = 0;

For[i = 1, i <= 10^6, i++,

If[EvenQ@list[[i]], num++]

];

num

如下图,用时1.73秒

保留上面的思路,单纯的将For循环改为Scan (相当于没有返回结果的Map),代码如下

num = 0;

Scan[If[EvenQ@#, num++] &, list];

num

如下图,用时0.91 秒

(Do循环用时1.00秒左右,篇幅所限就不传图了)

摒弃循环的思路,用其他内置函数写

Count[list, _?EvenQ] // AbsoluteTiming

(*直接用Count数出list中偶数的个数*)

Count[EvenQ /@ list, True] // AbsoluteTiming

(*用Map对list中的每个数判断是否偶数,然后用Count数出结果中True的个数*)

Select[list, EvenQ] // Length // AbsoluteTiming

(*选取list中的所有偶数,然后求结果列表长度*)

Count[EvenQ@list, True] // AbsoluteTiming

(*利用EvenQ的Listable属性直接判断list的每个数是否偶数,然后数出结果中True的个数*)

Sum[Boole[EvenQ@i], {i, list}]

(*对list中的每个元素判断是否偶数,将结果相加*)

结果如下图

这个遍历的例子举得不算特别恰当,但也能说明一些问题了:Mathematica中内置了许多神奇的函数,其中大部分只要使用得当效率都比循环高(而且不是一点半点)。就算非要用循环,也要记得(任何能用Do代替For的时候)

这个遍历的例子举得不算特别恰当,但也能说明一些问题了:Mathematica中内置了许多神奇的函数,其中大部分只要使用得当效率都比循环高(而且不是一点半点)。就算非要用循环,也要记得(任何能用Do代替For的时候)

Do比For快

,(遍历列表时)

Scan比Do快

用向量(矩阵)运算代替循环

这个例子来自如何用 Python 科学计算中的矩阵替代循环? - Kaiser 的回答,我只是把代码从Python翻译成了Mathematica而已。选这个例子是因为它有比较明确的物理意义,而且效率对比非常明显

代码如下

AbsoluteTiming[

n = 100;

u = unew = SparseArray[{{1, _} -> 1}, {n, n}] // N // Normal;

For[k = 1, k <= 3000, k++,

For[i = 2, i < n, i++,

For[j = 2, j < n, j++,

unew[[i, j]] =

0.25 (u[[i + 1, j]] + u[[i - 1, j]] + u[[i, j + 1]] +

u[[i, j - 1]])

]

];

u = unew;

];

u1 = u;

]

(*用三重循环,迭代3000次*)

ArrayPlot[u1, DataReversed -> True, ColorFunction -> "TemperatureMap"]

(*用ArrayPlot绘图*)

AbsoluteTiming[

n = 100;

u = SparseArray[{{1, _} -> 1}, {n, n}] // N // Normal;

Do[

u[[2 ;; -2, 2 ;; -2]] =

0.25 (u[[3 ;; -1, 2 ;; -2]] + u[[1 ;; -3, 2 ;; -2]] +

u[[2 ;; -2, 3 ;; -1]] + u[[2 ;; -2, 1 ;; -3]]),

{k, 1, 3000}];

u2 = u;

]

(*用矩阵运算,迭代3000次*)

ArrayPlot[u2, DataReversed -> True, ColorFunction -> "TemperatureMap"]

(*用ArrayPlot绘图*)

运行结果For循环用时136秒,矩阵运算用时不足0.5秒,且两者答案完全一样。在算法完全相同的情况下两种写法有着超过200倍的效率差距

(图片太长了这里就不直接显示了,链接放在下面)

http://pic4.zhimg.com/65d66161f4c674b1149651c32f69935f_b.png

===========================我是结尾的分隔线===============================

这个答案其实从一开始就跑题了,还写了这么长的目的就在于希望让大家切实地感受到循环的低效并安利一下Mathematica中其它高效的方法。正如wolray的答案中说的,既然选择了使用Mathematica就应该多利用些MMA独有的美妙函数,毕竟如果只是用循环的话C和Fortran之类的语言效率比MMA不知高到哪里去了。。。。。。

然我也不是让大家就不用循环了,毕竟很多时候循环的直观性和易读性带来的便利远远比那点效率重要。只是希望大家在循环之前能稍稍想一下,自己的目的是不是

一定要用循环?可不可以用内置函数代替循环?就像上面的几个例子,将循环换成内置函数程序的简洁性和效率都大幅提高,长此以往相信你一定会爱上MMA的~

题外话——关于用编译提速循环

MMA中如果一定要使用循环又对效率有一定要求的话,可以选择使用编译,效率能有极大的提高。比如上面的第4个例子使用Complie编译过后的Do循环

用时只有1.86秒,速度提升了将近100倍。如果电脑中有C编译器的话还可以在Compile中加入CompilationTarget ->

"C"选项,速度还能有所提升。编译过后的代码如下:

In[10]:= cf = Compile[{{n, _Integer}, {times, _Integer}},

Module[{u},

u = ConstantArray[0., {n, n}];

u[[1]] = ConstantArray[1., n];

Do[

Do[u[[i, j]] =

0.25 (u[[i + 1, j]] + u[[i - 1, j]] + u[[i, j + 1]] +

u[[i, j - 1]]),

{i, 2, n - 1}, {j, 2, n - 1}

], {k, 1, times}];

u

]

];

u3 = cf[100, 3000]; // AbsoluteTiming

ArrayPlot[u3, DataReversed -> True, ColorFunction -> "TemperatureMap"]

Out[11]= {1.86055, Null}

前3个例子也都可以通过编译提速很多,这里就不放代码了,有兴趣的同学可以自己动手试一试,如果遇到问题欢迎在评论中与我交流。

需要注意的是编译有很多注意事项,这里推荐一篇写的很好的教程,编译中常见的问题里面都有很好的讲解:怎样编译(Compile)/编译的通用规则/学会这6条,你也会编译

但是一般来讲编译很麻烦,而且再怎么编译效率也很难赶上直接用C,所以个人并不特别建议MMA初学者学习编译。

已赞过

已踩过<

你对这个回答的评价是?

评论

收起

python 矩阵运算 for循环_如何用 Python 科学计算中的矩阵替代循环相关推荐

  1. python 矩阵运算 for循环_如何用Python科学计算中的矩阵替代循环?

    比如求一个平面稳态导热问题,控制方程就是拉普拉斯方程: (我才发现原来有[插入公式]这个功能) 按照最简单的毅种循环来写就是: def laplace(u): nx, ny = u.shape for ...

  2. python 读取excel图片_如何用Python读取Excel中图片?

    公众号: 早起Python 作者:刘早起 大家好,在使用Python进行办公自动化操作时,一定少不了与Excel表格的交互,我们通常是用pandas处理表格数据,但大多数情况下,都是读取表格中的数值进 ...

  3. 怎么用python读取excel图_如何用Python读取Excel中图片?

    公众号: 早起Python 作者:刘早起 大家好,在使用Python进行办公自动化操作时,一定少不了与Excel表格的交互,我们通常是用pandas处理表格数据,但大多数情况下,都是读取表格中的数值进 ...

  4. python编程代码画画_如何用python编写一个绘制马赛克图像的自写程序

    Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发. 这篇教程将会展示如何用python的图形化包"Pygame"和基础的文件I/O来创建一 ...

  5. python搭建自动化测试平台_如何用python语言搭建自动化测试环境

    原标题:如何用python语言搭建自动化测试环境 技术分享:基于Python语言的Web自动化测试环境搭建 近期发现很多初学者在学习自动化的过程当中,在环境安装环节总是出现问题,所以详细的出一篇环境搭 ...

  6. 如何制作python检查小软件_如何用Python制作整蛊小程序

    原标题:如何用Python制作整蛊小程序 下面的整蛊程序,千万不要发代码,否则就实现不了你整蛊的目的了.完成后一定要打包成一个exe程序,再发给朋友使用 . 1. 使用 pip install pyi ...

  7. python rest api 测试_如何用Python编写REST API的单元测试

    在过去的几个月中,正在从事一个名为B的项目.它是带有简单Web UI的徽章生成器,用于添加数据并生成PDF可打印徽章.B后端现在已转移到REST-API并测试REST-API中使用的功能,我们需要一些 ...

  8. python的out模式_如何用python中的DataFrame列的模式替换NA值?

    我对Python(和本网站)完全陌生,目前正试图用它们的模式替换特定数据帧列中的NA值.我试过了各种不起作用的方法.请帮我看看我做错了什么:如何用python中的DataFrame列的模式替换NA值? ...

  9. 用python做一张图片_如何用python下载一张图片

    如何用python下载一张图片 这里要用到的主要工具是requests这个工具,需要先安装这个库才能使用,该库衍生自urllib这个库,但是要比它更好用.多数人在做爬虫的时候选择它,是个不错的选择. ...

最新文章

  1. 如何支持亿级用户分流实验?AB实验平台在爱奇艺的实践
  2. C语言的结构使用和结构对齐
  3. Memcached 数据缓存系统
  4. c语言猜拳游戏思考,这是一个猜拳游戏的程序 大家有更好的解决方法么?
  5. 3分钟搞定SpringBoot+Mybatis+druid多数据源和分布式事务
  6. 兼容所有浏览器的js判断横竖屏以及监听事件
  7. ISO20000/ISO27001体系认证最短周期
  8. 迁移学习(Transfer)
  9. 归并排序+快排+快速选择+桶排序
  10. 计算机领域所有SCI期刊,计算机领域的所有SCI一区期刊,这是最顶级期刊了
  11. Micro Surface Pro 鼠标一直闪烁的问题
  12. panda经典四道题期末考核分享
  13. ZXR10 1809 路由器 1800开启WEB配置界面调试方法
  14. Run-down Protection
  15. 【Python】输入一个整数,输出这个整数的所有数字和,例如输入256,则输出13
  16. anaconda python降级有影响吗,更新conda会导致降级和被取代的包
  17. 这样写的邮件,客户回复率几乎高达100%
  18. python 论文画图
  19. Python实现节假日判断,手动添加后续节假日
  20. Java中命令行调用大坑

热门文章

  1. 游戏到底哪里吸引我?
  2. 事务隔离级别(图文详解)
  3. 【面试大全】互联网面试软实力【必看】
  4. 服务器cpu对游戏的支持,还想使用服务器CPU玩游戏吗?实际上,Xeon E3-1231 V3时代不再是必需的...
  5. Openlayers记录(四)同一图层设置不同的点符号(大小、颜色等)。
  6. python量化交易:Joinquant_量化交易基础【四】:下单、函数、API
  7. 不小了,该谈朋友结婚了,年前能实现吗?
  8. ajax提交form表单数据serialize转为JSON
  9. linux 虚拟机网络配置
  10. scratch案例—跳舞的小女孩