文章目录

  • 导读
  • 界面展示
  • 更换命令行
  • 基于`Linux`的特点
  • 清空面板
  • 快速矩阵
  • 矩阵构造
  • 冒号表达式
  • 个数计算
  • 其他数学函数
  • 数据集的导入和导出
  • 统计图绘制
  • 统计图绘制样式
  • 散点图
  • 柱状图
  • 等高线
  • 极坐标
  • 饼状图
  • 选择支
  • 循环
  • 函数
  • 其他

导读

终于,使用Ubuntu系统的我遇到了最尴尬的问题:建模工具Matlab没有linux发行版。虽然可以使用wine勉强跑起来,但毕竟不是运行在Windows内核下,所以往往有很多事情都非常尴尬。所以,我看上了这一款:octave。不仅支持Ubuntu,还能够兼容Matlab,是非常不错的替代品。

界面展示

先看看octave的软件界面,体验一下吧。

可以看到左边由上至下依次是:文件目录工作空间历史记录,而右边则是命令行界面

是不是非常熟悉?没错,这简直不能再像Matlab了。即使顶部功能菜单并没有Matlab那么丰富,却也足够了。

更换命令行

如果你有丰富的shell编程经验,那么你应该对这个>>非常熟悉。Matlab使用的是>>MySQL使用的是>sqlplusOracle)使用的是>Python使用的是>>>Ubuntu普通用户使用的是$Ubuntu超管使用的是#……

如果说你用惯了想要换,还是可以的。直接输入

# 这段字符串复制自我的Ubuntu终端
PS1("sakebow@Lenovo-V310-14IKB:~$ ")

这样就能够保持和终端一模一样的风格了。当然为了区分也可以改称其他的,比如

# ……懂的都懂……
PS1("お兄ちゃん、頑張るね、大好きだよ~❤ ")

基于Linux的特点

当然,因为开源免费的octave是使用C语言基于Linux系统开发的,所以也会保留一些Linux系统的命令。比如:

  • pwd显示当前所在文件夹
  • ls显示当前文件夹中所有的文件
  • cd跳转到制定文件夹
  • exit退出程序

即使是安装在Windows系统下的octave也是能够使用这些命令的。

清空面板

Ubuntu系统中你可以直接使用Ctrl+L清空命令行。所有的指令会存在历史记录Command History栏内

当然你也可以输入clc并回车就能够清空命令行

快速矩阵

这些Octave内置的快速矩阵摘自摘自油土鳖上一位印度阿三的教程(英语略微有一些咖喱味,但已经很不错了

o n e s ( n , m ) = [ 1 ⋯ 1 ⋮ 1 ⋯ 1 ] n × m z e r o s ( n , m ) = [ 0 ⋯ 0 ⋮ 0 ⋯ 0 ] n × m e y e ( n ) = [ 1 0 0 ⋯ 0 0 1 0 ⋯ 0 0 0 1 ⋯ 0 ⋮ 0 0 0 ⋯ 1 ] n = E e y e ( n , n + 1 ) = [ 1 0 0 ⋯ 0 0 0 1 0 ⋯ 0 0 0 0 1 ⋯ 0 0 ⋮ 0 0 0 ⋯ 1 0 ] n × ( n + 1 ) \begin{matrix} ones(n, m)&=& \left[\begin{matrix} 1&\cdots&1\\ &\vdots\\ 1&\cdots&1 \end{matrix}\right]_{n\times m} \\ zeros(n, m)&=& \left[\begin{matrix} 0&\cdots&0\\ &\vdots\\ 0&\cdots&0 \end{matrix}\right]_{n\times m} \\ eye(n)&=&\left[ \begin{matrix} 1&0&0&\cdots&0\\ 0&1&0&\cdots&0\\ 0&0&1&\cdots&0\\ &&&\vdots\\ 0&0&0&\cdots&1 \end{matrix} \right]_n&=&E \\ eye(n, n + 1)&=&\left[ \begin{matrix} 1&0&0&\cdots&0&0\\ 0&1&0&\cdots&0&0\\ 0&0&1&\cdots&0&0\\ &&&\vdots\\ 0&0&0&\cdots&1&0 \end{matrix}\right]_{n\times(n+1)} \end{matrix} ones(n,m)zeros(n,m)eye(n)eye(n,n+1)​====​⎣⎢⎡​11​⋯⋮⋯​11​⎦⎥⎤​n×m​⎣⎢⎡​00​⋯⋮⋯​00​⎦⎥⎤​n×m​⎣⎢⎢⎢⎢⎢⎡​1000​0100​0010​⋯⋯⋯⋮⋯​0001​⎦⎥⎥⎥⎥⎥⎤​n​⎣⎢⎢⎢⎢⎢⎡​1000​0100​0010​⋯⋯⋯⋮⋯​0001​0000​⎦⎥⎥⎥⎥⎥⎤​n×(n+1)​​=​E​

rand(n,m)则是生成n行m列均匀分布随机数矩阵uniformly random matrix),每个数字都是介于0到1之间的7位小数,且每个数字出现概率服从均匀分布 U ( 0 , 1 ) U(0, 1) U(0,1);

randn(n,m)是生成一共n列m行正态分布随机数矩阵normally random matrix),每个数字服从正态分布 N ( 0 , 1 ) N(0, 1) N(0,1)。乍一看这组数据毫无特点,实际上是 P ( μ − σ < x < μ + σ ) ≈ 0.6826 P(\mu-\sigma<x<\mu+\sigma)\approx0.6826 P(μ−σ<x<μ+σ)≈0.6826。这也就说明了为什么数字里面会有大于 1 1 1和小于 − 1 -1 −1的数字了

矩阵构造

CC++JavaC#等等语言中构造矩阵永远是一个很难受的工程,拿Java中的List<List<?>>来说,向其中添加元素是一项无比复杂的工程。

而在octaveMatlab中,就只需要使用

>> s = [1, 2; 3, 4]
s = 1 23 4

在这里你可以使用逗号作为分割符,也可以仅用空格作为分割符。

如果你要用克莱姆法则解多元一次方程组,那么就需要几个矩阵拆拆解解。这个时候可以把一整个矩阵当作数字:

  • [A B]像是[1 2],将两个数字横着拼起来
  • [A; B]则是[1; 2],将两个数字竖着拼起来
  • A'是矩阵的转置,就是 A T A^T AT

当然,我们还有矩阵的选择:

  • S(m, n)是选取矩阵S第m行第n列的一个元素
  • S(m, [x, y, z])是选择矩阵中第m行第x、y、z列的一共三个元素。如果还需要添加元素则在[]内追加
  • 下方冒号表达式继续介绍

冒号表达式

如果你熟悉CC++JavaC#等等(Python除外),你应该会经常使用到冒号表达式,即是:

// 输出该学生是否可以购买打折的火车票
cout << 学生.学生证 === null ? "火车票不能打折" : "火车票可以打折" << endl;

但是在octaveMatlab就完全不一样了。冒号表达式会这么用:start[:step]:end,即创建一个从startend的数组,其中每个数字之间间隔step,默认step值为1,即依次递增。

>> s = 1 : 5
>> ans =
[1 2 3 4 5]
>>
>> s = 1:3:10
>> ans =
[1 4 7 10]

当然冒号不止这一个用途。刚刚我们说了矩阵的构造,在矩阵中冒号还能够用作选择器。

我们在选择矩阵中元素的时候会使用一个数组作为范围,而如果这个范围正好可以用冒号表示的时候,就可以是这样:

  • S(m, [start : end]),也就是说选取第m行从start开始到end结束的所有元素

  • 如果没有规定startend,也就像是:S(m, :),那么就是选取第m行一整行

个数计算

Java中,对集合使用size()方法求集合内元素个数,对数组使用length()方法求数组内元素个数。

octave中,我们两个都可以用,但是size()方法返回的是行和列两个数字,而length方法则是从size()方法返回的两个数字中选择一个最大的。举个例子:

假设你这个时候又闲着没事创建了一个随机数组rand(5, 1),那么size()方法返回的是[5 1]两个数字,前者是行数,后者是列数;而length()方法返回的是5,是51中较大的数。

同样的,如果你只有一个数组[1 2 4]size()方法返回的依然是[1 3]两个数,而length()方法就返回3

其他数学函数

  • ceil(x) - 取比x大的第一个最近的整数,即向上取整
  • floor(x) - 取比x小的第一个最近的整数,即向下取整
  • round(x) - 取距离x最近的一个整数。如果 x = 0.7 x=0.7 x=0.7,则结果为 1 1 1;如果 x = 0.3 x=0.3 x=0.3,则结果为 0 0 0
  • max(x) / min(x) - 取一个数组中最大/最小的数

对于max(x)min(x)在官方给的说明里面指明的是vector,也就是说这个函数同样适用于矩阵、向量等等。但是实际测试的时候是这样的:

>> rand(5, 3)
ans =0.097667   0.295360   0.7100650.858128   0.141471   0.7294320.073253   0.503299   0.3797300.329683   0.839168   0.0766560.662468   0.514276   0.020735
>>
>> min(ans)
ans =0.073253   0.141471   0.020735

不难发现,对比的时候将一整列作为一个数组进行纵向的对比,每一列选出了一个最小的。在上面这个例子中,数组ans[0..4][0..2]每一列选出了最小的,也就是ans[2, 0]ans[1, 1]ans[3, 2]max(ans)也是一样的算法,只不过会每列找出一个最大的。

数据集的导入和导出

如果有一天我们使用计算机去证明歌德巴赫猜想,把所有的数字塞进去日复一日地算,终于算出来了一大批数字。我们不可能使用人工一个个抄下来,肯定是让计算机自己保存。这个时候就用save命令让计算机保存所有的数字。

例如,我现在弄出了很大一批随机数randn(1000, 1000),但是我突然发现笔记本电不够了,得保存下来。就这么使用:save ${文件名} ${变量名},意思就是:将变量的值保存在指定中。当然你也可以指定别的后缀名,比如我这里选择:

save randn.json ans

于是就有了如下效果:

但是呢,为了能够更直观地区分各个文件,我们尽可能按照大家默认的规矩来,这里推荐万能的.csv文件;官方更是推荐使用.mat文件。更何况,我这里导出的文件并不符合json文件的编写规范。

就像是Java的导包一样,我们会使用import导入一整个jar包。而在octave中,我们将会使用load命令导入文件。

如果再次使用,我们就使用load命令,即:load randn.dat我这里是.json

看起来很简单?我们再来点奇葩的:

有一天你们哥几个凑一起跑数据,结果突然发现两个人风格极其相近以至于命名都完全一样。现在重新改已经很头疼了,怎么办?

我们就用临时文件

% 创建临时文件
f = tmpfile
% 将变量存入临时文件
save f variable
% {拿同名变量处理一大堆事情
} %
% 读取临时文件
load f
% 这个时候同名变量就被覆盖了

打个比方的话,就像是C语言的局部变量全局变量一样。

当然,这只是一个非常极端的例子,我们强烈建议各小组之间事先商量好再码字,正如SpringBoot所倡导的:“约束大于业务”、“习惯大于编码

统计图绘制

统计图必定是有数据支持的,但是现在没有数据……那么就随机生成吧:rand(1, 100)。于是工作空间中就有了ans这个变量,同时还有了一个共1行100列的矩阵,也就是数组。

然后,我们就画图:plot(ans),于是产生了一个很简单的折线图:

因为是随机生成的数字,所以也看不出什么规律。

你可能会有点惊讶,为什么明明只有ans一个变量,谈不上所谓因变量和自变量,他是怎么画出来的?实际上这里是将下标作为横坐标、ans的值作为纵坐标画出来的。

统计图绘制样式

如果说你不需要折线图,而是散点图,那么就更改绘图样式吧:plot(ans, '*')

当然你觉得*不太美观的话也可以换成中文的·中文输入下波浪线按钮不加shift)或者日文的日文输入下问号按钮不加shift

为了防止很多图像看混了,可以使用不同的颜色标记:plot(ans, '1')

各种各样的数字代表了各种各样的颜色,而各种各样的字符代表了各种各样的描点

如果你什么都不写,那么默认就是使用-,也就是折线图。

散点图

好吧,用plot画出来的散点图多少还是有点点奇怪。那么我们干脆用专门画散点图的方法:scatter

还是一样的,我们拿到了一组数据:x = randn(1, 100),另外我们再来一组数据:y = randn(1, 100),然后画出随机散点图:

同样的,我们能够使用家参数的方式改变图像的样式:scatter(x, y, '*')。只不过这里支持的字符就比较少了,经测试似乎仅支持将圆圈更换为*

柱状图

柱状图也是一种重要的工具,在统计总数并比较多条数据的差值时用得多。就比如100个服从正态分布的随机数构成的柱状图中,能够清晰地看出各个概率之间分布的差值:

我们知道, P ( 0 − 1 < x < 0 + 1 ) ≈ 0.6826 P(0-1<x<0+1)\approx0.6826 P(0−1<x<0+1)≈0.6826,所以数据比较倾向于向 ( − 1 , 1 ) (-1, 1) (−1,1)这个区间集中。

等高线

就像是地理的等高线、电磁场的等势线一样,存在的目的就是为了说明哪一段是数值上相等的。在绘制的时候,我们需要提供一个至少两行两列的矩阵,然后就由contour方法寻找矩阵中值算出等高线。

比如对于 a n s = [ 1 2 3 4 5 6 7 8 ] ans=\left[\begin{matrix}1&2\\3&4\\5&6\\7&8\end{matrix}\right] ans=⎣⎢⎢⎡​1357​2468​⎦⎥⎥⎤​这个矩阵画出来的等高线就是contour(ans)

极坐标

高中我们认识并狠狠地练习了极坐标这些题目,所以我们就直接从最简短的开始: ρ = 2 cos ⁡ θ \rho=2\cos\theta ρ=2cosθ。相信你很清楚这个等式可以化为 x 2 + y 2 = x x^2+y^2=x x2+y2=x,是以 ( 1 , 0 ) (1,0) (1,0)为圆心、 1 1 1为半径的圆。

那么就确定两个变量:p = linspace(0, 1)o = linspace(0, 2 * pi)

注:linspace(x, y) = x:0.01:y,即从x到y中每隔0.01取一个点

然后,画极坐标:polar(p, o)

就出现了这样的图:

似乎和我们平常见到的直角坐标系不一样。不过没有关系,是不是在很多影视作品中看到类似的?雷达嘛。在战场上,你发送了敌机的 ( x , y , z ) (x, y, z) (x,y,z)坐标,这谁懂啊。干脆点,报哪个方向方向多少度,往那打。这种情况下极坐标比直角坐标好用多了。

还有其他很有意思的:比如我们将刚刚的po调换一下位置,就成了螺旋线。

饼状图

饼状图只是为了查看占比,所以大批量的随机数在这里并不适合作为样本。所以这里就随机生成三个数:ans = randn(1, 3)

由于饼状图是组内比较,所以只能使用一组数据,即行向量或者列向量作为参数。如果生成ans = randn(10, 10)作为样本则会报错。使用时还请注意。

可以看到,octave拿到数据之后立马进行了权重的计算,最终得出了这个结果。所以我们在实际实验中就只需要把数据整理成行向量或者列向量传入,octave就能够在一定程度上。

既然饼状图是查看一个部分或者多个部分的占比,为了让图片更清晰,就可以让一些部分联系起来。

时间回溯到你收集猫娘数据的那些日子(别吐槽了,听就是了)

你了解到全世界的猫娘们的年龄从0岁开始往上的数量依次是neko = [16247, 18752, 19165, 17251, 11471, 18714, 10961, 5428, 13725, 8715, 10031, 13298, 8715, 9716, 4562, 9612, 3610]随手瞎打的)。你想清晰地看出在0到3岁的猫娘占比,于是你使用第二个参数:explode。这个参数应当是一个数组。如果数值为0,则会与下一个块区相接;而如果非0,即使是负数也会明显分开。

于是我们为了清晰地看出0到3岁的小猫娘的数量,我们使用pie (neko, [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),就会产生这样的效果:

可以看到,设置为非零的前三个部分被分开了,占比 8 % + 9 % + 10 % = 27 % 8\%+9\%+10\%=27\% 8%+9%+10%=27%。这是不是比不突出任何元素的饼图看起来更直观呢?

选择支

当然,作为一门高级语言,选择支是必要的。

如果你是想通过选择支筛选不同年龄段,那么就使用:

if age < 3,% filter for age < 3
elseif age < 10,% filter for 3 < age < 10
else,% filter for age > 10
end;

这个逗号估计就是在命令划分的时候不太好识别标志加上的。虽然和JavaPython略有出入,但我相信这绝对有他的道理。

循环

while循环相信各位都熟悉得不能再熟悉了。实际上whileif的用法实际上是一样的。毕竟都是判断条件并转入选择支。唯一的区别估计就是if语句能够接else ifelse来筛选不同的条件,而while只能始终选择同一个条件。

for循环相比while循环又多了一个神奇的功能:将一个集合里的每一个元素创建索引,并且这个索引仅作用于for循环中,是区域变量。

% 假设nekos里面保存了每只猫娘的年龄(age)和姓名(name)
for neko = nekos,if neko.age > 10,sprintf("%i", neko.name)end;
end;

如果你确定这些猫娘有着不同的名字,并且你一定要找到那只叫做“chocola”的猫娘(没……没夹带私货……真的!),那么就这么来:

for neko = nekos,if neko.name == 'chocola',sprintf("%i", neko.age)break; % 跳出一层循环end;
end;

有了这个break,一旦找到了chocola就会退出并显示她的年龄。

而如果这些猫娘有重名却有着不容的铃铛编号呢?那么就全找出来。

for neko = nekos,if neko.name == 'chocola',sprintf("%i", neko.id)continue; % 强制结束本次循环end;
end;

有了continue,程序就不会结束,反而是直接结束continue后面的所有步骤,强行结束本次循环。全部显示出来之后我们再对比这些编号是不是我们想要的编号。

JavaPython等等有着非常多的相似之处呢。即使完全没接触过matlab,相信你们也能用丰富的编程经验理解用法。

函数

函数看起来非常高端,实际上你可以看成多个普通命令的合集。

函数是有固定的套路的:

function ${variable} = ${function name} (${argument list})% to do list
endfunction;

但是你得明白:函数毕竟是一个包含了很多行的整体。如果你使用纯命令行编辑整个函数,一旦某个地方有所疏忽,一运行函数就有可能会报错,然后整个函数重写。这是相当考验熟练度、耐心和细心的工作。当然,肯定不会让你有这么难受的体验的。

octave为了能够在数学处理上由所优势,就决定兼容matlab所使用的.m文件。在这个文件中,我们能够使用各种各样的变量记录函数的定义,这样即使出现了错误我们也能够通过错误信息定位到不正确的地方并修改。这样就避免了整个函数重写的惨痛经历。

如果你只有命令行,或者说只愿意使用命令行,octave也是提供了专门的命令:edit ${file name}。如果是Ubuntu系统,octave将会在~/octave文件夹下创建或者修改文件。在这里尤其注意文件的命名,一方面是因为这样子能够很清晰地弄清楚什么文件保存了什么函数,另一方面也是因为有些文件名是octave内定的特殊文件,比如test.moctave规定的测试文件,其中含有非常多的内置函数和测试函数供用户调用、测试。而如果只是一般的命名就没有什么特殊的,只是会加上很多版权说明,并默认提供一个空函数模板以供用户根据需求修改。

有点难懂?那我们举个例子,主人公还是那个热爱猫娘的你。这次的你尽了全力也没能收集全所有的数据,有些猫娘一被问到年龄就狠狠地挠你的嘴,有些则因为怕生逃掉了,也有些则在接近之前你就被主人当成可疑人物带走了……总之,你虽然找到了20万只猫娘,却只收集了5000条残缺不全的数据,不是掉了这个就是少了那个。但是该寻找的还是要寻找,那就是查清相同年龄里成绩最好和成绩最差的两只猫娘的信息。

在写这个函数之前,我们首先明白几个非常重要的点:

  • octave是以matlab为模板创建的全平台兼容的软件,所以有什么不懂可以直接查询matlab的教程;
  • octavematlab非常相似,都是以C为基础搭建的,所以并没有面向对象编程的概念,整个程序就是为了面向过程而设定的。

所以,我们如果使用octave处理猫娘们的数据的时候,只能把所有想要的全部手打或者通过脚本筛选,最终达成只包含需要被处理的部分的、单纯列出所有而不是分类整合的数据集。如果是使用各种各样括号分开的json数据则无法被处理为一个个对象,却只能分成许许多多的单条数据。

% 文件名:filter.m
% 从一堆数据中寻找最小的数据
function filter_mini = filter(x)ret = x(1)for i = 2:length(x),if x(i) < ret,ret = x(i)endif;endfor;
endfunction;

在这里需要非常注意的是:一个文件只能编辑一个函数每个函数的名称必须和文件名保持一致,否则会报警告:函数名和文件名不匹配。调用则是很普通的使用文件名即可,代入参数便能得到结果。

可是,我要找出猫娘的id啊,你这只能找出分数欸。那就这样,我们先按照猫娘的id顺序排列,我们找出最大和最小的索引,再从这些索引中找出id就好咯。

function [low, low_index, high, high_index] = filter(x)low = x(1); high = x(1); low_index = 0; high_index = 0;for i = 2:length(x),if x(i) < low,low = x(i)low_index = ielseif x(i) > high,high = x(i)high_index = iendifendfor
endfunction

这样看起来没什么问题。但是却依然引出了另一个问题:一旦找出符合if语句的分数,程序就会立马返回并打印,然后你就发现了一大堆数字堆在那里,并只能通过肉眼筛选真正符合条件的数字。如果说明得学术一点,那就是:“打印出大量的局部最优解,并只能通过肉眼寻找全局最优解”。是不是很让人抓狂?

还是有解决办法的。也就是在调用的时候规定返回值:

[a, b, c, d] = filter(param)

这样的话虽然还是会打印一大堆数字,却能够很明显地看出全局最优解的结果了。

当然,有函数就一定有错误处理:

function [low, low_index, high, high_index] = filter(x)% 如果不是列向量或者行向量,报错。if isvector(x),error("filter expects a vector")endif;low = x(1); high = x(1); low_index = 0; high_index = 0;for i = 2:length(x),if x(i) < low,low = x(i)low_index = ielseif x(i) > high,high = x(i)high_index = iendif; % 这里的endif和endfor也可以换成endendfor;
endfunction;

其他

这些就已经是全部的基本操作了。如果还需要精进,还需要尝试攻克数学建模的一些经典书籍。接下来将说明一些次要的事情:

如果你是Windows环境下的纯命令行,那么你在执行了上面提到的一些画图命令之后,还需要执行hold on命令让图像显示出来,而close命令则是关闭图像。当然,毕竟是Windows窗体程序,你也可以选择点击右上角的关闭窗口按钮关掉这张图片。

建模工具:octave相关推荐

  1. 基于uml的系统分析的网上商城_UML建模工具Enterprise Architect最新版有哪些新功能呢?立即查看...

    Enterprise Architect是一个对于软件系统开发有着极好支持的CASE软件(Computer Aided Software Engineering).EA不同于普通的UML画图工具(如V ...

  2. UML软件开发与建模工具Enterprise Architect发布最新版本v15.2

    Enterprise Architect是一个对于软件系统开发有着极好支持的CASE软件(Computer Aided Software Engineering).EA不同于普通的UML画图工具(如V ...

  3. UMLChina: trufun Plato是中国唯一的UML建模工具

      在UMLChina最新发布的"厂商"栏目中,Trufun Plato是唯一的中国人自己的UML建模工具:[url]http://www.umlchina.com/Tools/N ...

  4. (转)轻量级 UML 建模工具JUDE 介绍(二)

    [译]Learn UML with JUDE(二) 六. UML about Bowling 现在都准备好了,我们可以开始画diagram了.我们画什么diagram呢?你最近有去打过保龄球吗?我非常 ...

  5. PDMan-2.1.3 发布:用心开源,免费的国产数据库建模工具

    2019独角兽企业重金招聘Python工程师标准>>> 一.软件介绍 PDMan 是一款开源免费的数据库模型建模工具,是PowerDesigner之外另一种更好的选择.支持Windo ...

  6. UML建模工具EA和Rose比较

    UML建模工具EA和Rose比较 自从1997年正式发布UML以后,大量商用UML建模CASE工具粉墨登场.这样为我们提供了许多的选择,同时也要求我们在选择正确的UML建模工具以更好地适应我们业务和软 ...

  7. uml图工具_UML建模工具更新情况(二)

    UMLChina整理的UML建模工具列表请见http://www.umlchina.com/tools/search.aspx最近一段时间更新: 工具最新版本:Software Ideas Model ...

  8. uml 工具_UML建模工具更新202008(1)Rhapsody名字不再有Rational

    UMLChina整理的UML建模工具列表请见http://www.umlchina.com/tools/search.aspx 最近一段时间更新: 工具最新版本:IBM Engineering Sys ...

  9. uml 工具_【推荐】灵活而丰富UML建模工具Enterprise Architect!

    Enterprise Architect是一个对于软件系统开发有着极好支持的CASE软件(Computer Aided Software Engineering).EA不同于普通的UML画图工具(如V ...

最新文章

  1. 使用 sched_setaffinity 将线程绑到CPU核上运行
  2. 常看 Shell: 文本文件操作
  3. xamarin使用mysql_[开源] .NetCore .NetFramework Xamarin 使用 ORM FreeSql 访问 MySql
  4. 强大js web甘特图制作之甘特图组件和数据对象
  5. 在android studio中如何创建一个类来继承另外一个类_在Android使用Transition API检测用户活动...
  6. Android 系统(229)---OTA
  7. 电动汽车告急?特斯拉、蔚来之后 一辆比亚迪新能源车突然自燃...
  8. mysql笔试_mysql笔试题
  9. C#的委托(delegate、Action、Func、predicate)
  10. java学习中,instanceof 关键字 和 final 关键字、值的传递(java 学习中的小记录)...
  11. java之jsoup爬虫
  12. python培训教程 ppt
  13. dell r710重装系统_dell服务器安装系统指南
  14. 2022年NPS基准:NPS分数达到多少算好?
  15. Wireshark之远程抓包
  16. 大学计算机应用基础第二版习题答案,大学计算机应用基础练习题库及答案.docx...
  17. word中公式全篇一次性转math type公式方法,而且出现omml2mml.xsl 问题的解决方法(有效!!!)
  18. html表格标题标签_HTML标题标签
  19. 初入Kaggle之数据集的使用及预测结果生成
  20. 解密QQ号(stl库)

热门文章

  1. 你是谁的蘑菇,你的蘑菇又在哪?
  2. VS Code快速实现Git PR操作
  3. python仿360界面_python实现360的字符显示界面
  4. 最近发现有很多人一直在问苹果ID双重认证怎么关闭。
  5. 《炬丰科技-半导体工艺》硅片湿法清洗技术
  6. stm32笔记02——ST-Link下载器使用说明
  7. SRS-开源流媒体服务器
  8. ros环境下配置orb-slam2遇到的问题
  9. core网络课程整理(core概述及启动讲解)
  10. 基于QT的游戏修改器