我的编程空间,编程开发者的网络收藏夹
学习永远不晚

如何理解linux中的数值计算的语言

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

如何理解linux中的数值计算的语言

这篇文章主要介绍“如何理解linux中的数值计算的语言”,在日常操作中,相信很多人在如何理解linux中的数值计算的语言问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何理解linux中的数值计算的语言”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

一、元组和数组

  如果数值计算仅仅只是两个标量之间的加减乘除,那就不需要我在这里浪费口舌了。向量啊、矩阵啊、多维数组啊什么,才是数值计算真正的主角。所以,适合做数值计算的编程语言必须有一个好的方式表示数组,特别是多维数组。哪种方式好呢?是这样:

代码如下:

int a[m][n][k];

还是这样:

代码如下:

int a[m,n,k];

  看似没有什么差别,但是如果你想获取数组a的形状呢?比如这样:

代码如下:

? = a.shape();

或者再更进一步,想改变数组a的形状呢?比如这样:

代码如下:

a.reshape(?);

  在上面的代码中,“?”究竟应该用什么代替呢?

  如果让我给出答案,我会说:要用元组。很多编程语言中都有元组的概念,比如Python。元组就是用逗号隔开的几个值,可以加圆括号,也可以不加。我觉得加上圆括号后可读性更好。比如(a,b)是元组,(3,4,5)也是元组。如果写成[3,4,5]那就是数组了,在Python中,也称之为列表。不过Python的列表功能比数组要强大,因为数组只能保存同一种数据类型的值,而列表可以保存任何对象。数组一般情况下不能动态改变长度,而列表可以。Octave语言中使用cell array这个术语来表示可以保存不同类型对象的容器。Octave中的数组和矩阵是可以动态改变长度的。C语言的数组没有动态改变长度这个功能,而如果使用C++的话,则必须使用vector<>模板类。

  我认为,一个好的编程语言必须要有“元组”这个一个概念,必须能够用好大括号、中括号和小括号。在有没有元组这个问题上,很多语言做得不好,C语言没有,C++也没有,Java没有,C#这个有很多新功能的语言也没有,不要告诉我有Tuple<>模板类可以用,那个真的没有语言内置的元组功能好。在能不能用好大中小括号这个问题上,C语言就做得不好。你看它不管是初始化数组,还是初始化struct,都是用大括号。而Python和JSON就做得很好嘛,初始化数组用中括号,初始化对象或字典的时候采用大括号。如果加上小括号表示元组,那就齐活儿了。

  数值计算可以针对标量、一维数组、二维数组以及n维数组进行。数组可以如下组织,如下图:

如何理解linux中的数值计算的语言

  元组最大的用途就是可以用来表示数组的形状了。比如一维数组的形状为(n,),请注意其中的逗号不能省略。二维数组的形状(m,n),三维数组的形状(m,n,k),依次类推。另外,元组可以用来对数组中的元素进行索引。比如:

代码如下:

a = [ [1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16] ];b = a[2,3,3];

  元组还有一个很大的用途,那就是可以让一个函数返回多个值。C语言在这个方面是做得比较丑陋的,如果一个函数要返回多个值,只能给这个函数传指针或者多重指针作为参数,C++可以传引用,C#更加画蛇添足,专门有一个out关键字用来修饰函数的参数。微软你真是的,你既然能想到out,你就不能想到元组吗?常见的例子,比如meshgrid()函数可以同时初始化两个数组,peak()函数可以同时初始化三个数组。你看它们用元组多方便:

代码如下:

(xx, yy) = meshgrid(x, y);(xx, yy, zz) = peak();

   另外,元组还可以这样用,比如交换两个变量的值:

代码如下:

(a,b) = (b,a);

二、数组初始化

  在数值计算中,数组的初始化也是非常重要的一环。如果像C语言这样写:

代码如下:

int a[100] = {1, 2, 3, 4, ... , 100};

估计很多人是要骂娘的。这样写:

代码如下:

for(int i=0; i<100; i++){    a[i] = i+1;}

也不优雅。我只是想初始化一个数组而已,怎么就非得要写一个循环呢?如果是二维数组呢,就得两层循环,三维数组就得三层。真的是太闹心了。

  另外,如前所述,我也不喜欢在初始化数组的时候用大括号。我觉得中括号就是为数组而生。比如这样:

代码如下:

a = [1, 2, 3, 4];

这就是一个一维数组,但是如果这样写:

代码如下:

a = [ [1, 2, 3, 4] ];

就是一个行向量。如果写成这样:

代码如下:

a = [ [1], [2], [3], [4] ];

那么这就是一个列向量,如下图:

如何理解linux中的数值计算的语言

   当然,上面的示例只有四个数字,这么写一写无可厚非。如果是很多数字呢?或者很多维的数组呢?这时就必须得用到很多初始化函数了,而且这些初始化函数最好能接受元组作为参数来决定数组的形状。比如这样:

代码如下:

a = xrange( 1, 60, (3,4,5) );  //用1到60的数字初始化一个3*4*5的数组
b = randn ( (3, 4, 5) ); //用随机数初始化一个3*4*5的数组

  其它的初始化函数还有linspace()、logspace()、ones()、zeros()、eyes()等等。这些函数还可以配合reshape()使用,比如这样:

代码如下:

c = linspace(0, 2*pi, 60).reshape(3, 4, 5);

  在所有的这些初始化中,元组都是重要的组成部分。

三、range和切片

  其实,range除了可以是一个函数,还可以更省点儿事,像这样写:

代码如下:

r = 0:10:2;  //0,2,4,6,8,10
s = 11:0:-3; //11,8,5,2

  在某些语言中,也把这个功能叫切片。其实就是“:”的灵活运用,有标点符号可以用当然不能浪费嘛。使用切片,只需要指定起始值、终止值和步长,就可以获得一个数字序列。

  但是,“:”最大的用途并不是用来对数组进行初始化,而是对数组进行索引。比如,a是一个三维数组,可以通过切片来获取其中的一部分数据。见下面的代码:

代码如下:

a = range(1, 60).reshape(3, 4, 5); // a是一个三维数组
b = a[1, 2:3, 1:4]; // b是一个二维数组,其值为[ [12, 13, 14, 15], [17, 18, 19, 20]]

  切片除了可以指定起始值和终止值外,也可以指定步长。当然,也可以只用一个单独的“:”,代表取这一整个轴。关于轴的概念,可以看我前面的图片。见下面这样的代码:

代码如下:

a = range(1, 60).reshape(3, 4, 5); // a是一个三维数组
b = a[1, :, :]; // b的值为二维数组[[1,2,3,4,5], [6,7,8,9,10],  [11,12, 13, 14, 15], [16,17, 18, 19, 20]]

四、不写循环

  在对多维数组进行加减乘除的时候,如果使用传统的像C这样的语言,则避免不了要写循环。比如要计算两个多维数组的加法,不得不写这样的代码:

代码如下:

m = 10;
n = 20;
k = 30;
a = randn(m, n, k); //形状为(m, n, k)的三维数组,初始化为随机值
b = randn(m, n, k); //形状为(m, n, k)的三维数组,初始化为随机值
for(int i=0; i<m; i++){
   for(int j=0; j<n; j++){
       for(int p=0; p<k; p++){
           c[i, j, p] = a[i, j, p] + b[i, j, p];
       }
   }
}

  上面的代码当然远不如下面这样的代码简洁:

代码如下:

C = A + B;

  所以不写循环基本上就成了所有数值计算语言的标准配置。Matlab和Octave是这样,NumPy是这样,R语言也是这样。C++也在追求这样,因为C++中有运算符重载的功能,所以可以对矩阵类重载加减乘除运算符。但是C++中运算符的基础设施有缺陷,比如它没有乘方运算符(幂运算符),在Octave和NumPy中,都可以这样计算$x^y$:x**y。但是在C++中,只有使用函数power(x, y)。不要想^运算符,它是一个位运算符,所以取幂只有使用**了。另外,多维数组运算还有特例,比如二维数组之间加减乘除,既可以是逐元素的加减乘除,也可以是矩阵的加减乘除。向量计算也有特例,既可以是逐元素加减乘除,也可能是向量内积(点乘)。如果正好是长度为3的向量,还可以计算叉乘。这些运算符都需要重新定义,所以虽然C++有重载运算符的机制,但是因为这些运算符完全超越了C++的基础设施,所以C++也没有办法写得很优雅。

  不写循环还有一个优点,那就是可以对运算速度进行优化。优化是编译器或解释器的责任,写数值计算程序的人可以完全不用费心。编译器或解释器可采取的优化方式有可能是利用SSE等多媒体指令集,也可能是发挥多核CPU的多线程优势,甚至是使用GPGPU计算都有可能。如果用户非要写成C语言那样的循环,而他又不会内联汇编或OpenMP的话,那么就谈不上什么运算速度的优化了。

五、广播

  不写循环,直接把两个多维数组进行加减乘除当然省事。但是如果两个数组的形状不一样呢?比如一个二维数组加一个行向量,或一个二维数组加一个列向量,甚至是数组加减乘除一个标量,会出现什么情况呢?

  不用担心,在面向数值计算的语言中,一般都有“广播”这样一个特性。当两个数组的形状不一样时,形状比较小的那个往往可以在长度为1的维度上进行广播。如下图:

如何理解linux中的数值计算的语言

六、奇异索引

  Fancy indexing,有的书上翻译成花式索引,但我认为叫奇异索引比较好。它就是指一个低维的数组,可以使用高维的数组进行索引,最后得到的结果是一个高维的数组。如果索引中含有切片,可能会得到一个更高维度的数组作为结果。

  这个概念理解起来比较难。特别是再配合切片使用,更加增加其复杂性。所谓一图胜千言,先看普通索引的情况:

如何理解linux中的数值计算的语言

   前面提到,对多维数组进行索引的时候需要用到元组,元组的长度等同于数组的维数。对于普通索引而言,元组的各个部分要么是整数,要么是切片。而对于奇异索引而言,索引元组的各个组成部分都可能是多维数组或者切片。如果是多维数组,则最后得到的数组的形状和索引数组的形状相同,如果配合切片,则可能得到更高维的数组。如下图:

如何理解linux中的数值计算的语言

七、函数调用

  编程语言发展这么多年,一直在进化,也一直在相互靠拢。对于一个编程语言来说,是应该面向过程还是面向对象?是静态类型还是动态类型?这些都是值得思考的地方。但是在函数调用方面,有一些思想倒是可以学习。

  在C语言这样比较古老的语言中,对于函数的参数来说,只有位置参数一种。也就是说,像一个函数传递参数的时候,只能正确的参数放到正确的位置,而且参数的个数必须和函数定义的相同。这是最原始的函数调用思想。

  紧接着,在某些编程语言如Java、C#中,有了可选参数这个概念。但是可选参数要放到参数列表的最后面,而且必须提供默认值。当调用函数时如果指定了这个参数,则使用调用时指定的值,否则使用默认值。

  但是我觉得适合数值计算的语言必须还得更进一步,提供关键字参数的功能。什么是关键字参数呢?比如对数据进行绘图的时候,需要指定线型、标签、标题等各种属性,可以这样调用函数:

代码如下:

plot(x, y, marker="*", color="r", line, title="...", legend="...", xlabel="...", ylabel="...");

  每一个参数调用的时候都可以指定它的名字,这样我们就不用去死记各个参数的位置,是不是很方便呢?

八、生态环境

  对于一门编程语言而言,生态坏境很重要。在数值计算领域更是如此。因为很多数值计算的库都是专业的人士写给专业人士看的,比如物理专业的写物理领域的算法,气象专业的写气象专业的算法,所以不大可能有一个全面的官方的,像C或C++这样一个由ANSI定义的库。

  广泛接受开源社区的贡献是一个比较好的办法。Perl是这样,Python也是这样,新兴的R语言也是这样。Perl有CPAN,Python有PyPI,R语言也有CRAN。至于Matlab,那更是有各种各样的工具包。

到此,关于“如何理解linux中的数值计算的语言”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

如何理解linux中的数值计算的语言

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

如何理解linux中的数值计算的语言

这篇文章主要介绍“如何理解linux中的数值计算的语言”,在日常操作中,相信很多人在如何理解linux中的数值计算的语言问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何理解linux中的数值计算的语言”的疑
2023-06-13

linux中shell的变量的数值计算

1、expr命令a=123 expr $a + 10 ##加法 expr $a - 10 ##减法 expr $a \* 10
2022-06-04

r语言怎么计算数组的平均值

在R语言中,可以使用mean()函数来计算数组的平均值。例如,对一个包含数字的数组进行平均值计算可以这样做:# 创建一个包含数字的数组nums <- c(1, 2, 3, 4, 5)# 计算数组的平均值average <- mean(
r语言怎么计算数组的平均值
2024-03-06

Go语言如何计算字符串中的单词数

本指南详细介绍了在Go语言中计算字符串单词数的三种方法:字符串拆分、正则表达式和循环与分隔符。还讨论了第三方库、效率考虑和一个代码示例,以展示这些方法的实际应用。
Go语言如何计算字符串中的单词数
2024-04-02

C语言如何计算字符串中的单词数

本文详细讲解C语言计算字符串单词数的方法,包括获取字符串、遍历字符、检查字符类型、特殊情况检查和打印结果。该算法时间复杂度为O(n),适合大多数场景,但对于超长字符串和连续空格处理能力较弱。
C语言如何计算字符串中的单词数
2024-04-02

C语言如何计算一个整数的位数

这篇文章主要介绍了C语言如何计算一个整数的位数,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2022-11-16

Kotlin语言中是如何处理null值的

Kotlin语言中是如何处理null值的?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Kotlin null的处理详解NullPointerException,
2023-05-31

如何在C语言中计算大数阶乘

今天就跟大家聊聊有关如何在C语言中计算大数阶乘,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。C语言是什么C语言是一门面向过程的、抽象化的通用程序设计语言,广泛应用于底层开发,使用C语
2023-06-15

linux中shell怎么计算变量的数值

这期内容当中小编将会给大家带来有关linux中shell怎么计算变量的数值,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。1、expr命令a=123expr $a + 10
2023-06-09

c语言如何计算n的阶乘

本篇内容主要讲解“c语言如何计算n的阶乘”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“c语言如何计算n的阶乘”吧!c语言计算n的阶乘的方法:1、通过for循环计算阶乘,代码如“for (i =
2023-07-04

C语言如何计算两个数的最小公倍数

这篇文章主要介绍了C语言如何计算两个数的最小公倍数,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2022-11-16

javascript如何计算数组中某值的出现次数

这篇文章主要介绍了javascript如何计算数组中某值的出现次数问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
2023-01-17

编程热搜

目录