实用工具函数

TianYuan 提供了一系列实用工具函数,涵盖输入输出、类型转换、工作空间管理、方程求解等功能。这些函数让编程更加便捷高效。

输入输出函数

disp - 显示变量

语法 说明
disp(x) 显示变量 x 的值
disp(str) 显示字符串

参数说明

  • x: 标量、矩阵或字符串
  • 矩阵会以格式化的形式显示
  • 不返回值,只输出到控制台

示例

# 显示标量
x = 3.14159
disp(x)

# 显示字符串
disp('Hello, TianYuan!')

# 显示矩阵
A = [1 2 3; 4 5 6]
disp('矩阵 A:')
disp(A)

# 显示计算结果
result = sqrt(2)
disp('sqrt(2) = ')
disp(result)

# 在循环中使用
for i = 1:5
    disp(['迭代 ', num2str(i)])
end

# 显示向量
v = [1, 2, 3, 4, 5]
disp('向量:')
disp(v)

# 调试输出
x = 10
y = 20
sum_xy = x + y
disp(['x = ', num2str(x), ', y = ', num2str(y)])
disp(['x + y = ', num2str(sum_xy)])

fprintf - 格式化输出

语法 说明
fprintf(format, ...) 按照格式字符串输出数据

格式说明符

  • %d%i: 整数
  • %f: 浮点数(默认6位小数)
  • %.2f: 浮点数(指定小数位数)
  • %e: 科学计数法
  • %s: 字符串
  • \n: 换行符
  • \t: 制表符

示例

# 基本格式化输出
x = 42
fprintf('x 的值是 %d\n', x)

# 浮点数格式化
pi_val = 3.14159265
fprintf('π ≈ %.2f\n', pi_val)      # 保留2位小数
fprintf('π ≈ %.5f\n', pi_val)      # 保留5位小数

# 科学计数法
large_num = 1.23e10
fprintf('大数: %e\n', large_num)

# 多个参数
x = 10
y = 20
fprintf('x = %d, y = %d, x + y = %d\n', x, y, x + y)

# 表格输出
fprintf('编号\t姓名\t\t分数\n')
fprintf('1\t张三\t\t85.5\n')
fprintf('2\t李四\t\t92.0\n')
fprintf('3\t王五\t\t78.5\n')

# 循环中的格式化输出
for i = 1:5
    square = i^2
    cube = i^3
    fprintf('%d 的平方是 %d,立方是 %d\n', i, square, cube)
end

# 精度控制
value = 1/3
fprintf('默认精度: %f\n', value)
fprintf('2位小数: %.2f\n', value)
fprintf('10位小数: %.10f\n', value)

类型转换函数

double - 转换为双精度

语法 说明
double(x) 将 x 转换为双精度浮点数

示例

# 确保是双精度类型
x = 42
y = double(x)
disp(y)

# 矩阵转换
A = [1, 2, 3; 4, 5, 6]
B = double(A)
disp(B)

# 注意:TianYuan 中所有数值默认都是 double 类型
# 此函数主要用于显式类型转换和兼容性

num2str - 数值转字符串

语法 说明
num2str(x) 将数值转换为字符串
num2str(x, precision) 指定精度的数值转字符串

示例

# 基本转换
x = 42
s = num2str(x)
disp(['字符串: ', s])

# 浮点数转换
pi_val = 3.14159
s_pi = num2str(pi_val)
disp(['π = ', s_pi])

# 字符串拼接
a = 10
b = 20
message = ['a = ', num2str(a), ', b = ', num2str(b), ', sum = ', num2str(a + b)]
disp(message)

# 构建动态标题
iteration = 5
title_str = ['迭代次数: ', num2str(iteration)]
disp(title_str)

# 科学计数法的数
large = 1.23e15
s_large = num2str(large)
disp(['大数: ', s_large])

# 构建文件名
file_id = 42
filename = ['data_', num2str(file_id), '.txt']
disp(['文件名: ', filename])

字符串操作函数

函数说明
strcat(s1, s2, ...)连接字符串
strtrim(s)去除首尾空白字符
upper(s)转大写
lower(s)转小写
strcmp(s1, s2)字符串比较(大小写敏感),相等返回 1
strcmpi(s1, s2)字符串比较(忽略大小写)
strfind(s, pattern)返回所有匹配位置的行向量
strrep(s, old, new)替换所有匹配子串
str2num(s)字符串转数值
str2double(s)字符串转浮点数,与 str2num 等价
sprintf(fmt, ...)格式化字符串,返回字符串(不输出)
length(s)返回字符串长度

示例

% strcat - 连接字符串
s = strcat("Hello", ", ", "World")   # "Hello, World"

# strtrim - 去除首尾空白
s2 = strtrim("  hello  ")            # "hello"

# upper / lower - 大小写转换
upper("hello")   # "HELLO"
lower("WORLD")   # "world"

# strcmp / strcmpi
strcmp("abc", "abc")    # 1
strcmp("abc", "ABC")    # 0
strcmpi("abc", "ABC")   # 1

# strfind - 查找子串位置
positions = strfind("abcabcabc", "bc")  # [2 5 8]

# strrep - 替换子串
result = strrep("hello world", "world", "TianYuan")  # "hello TianYuan"

# str2num - 字符串转数值
x = str2num("3.14")   # 3.14

# sprintf - 格式化为字符串
s = sprintf("x = %d, y = %.2f", 3, 3.14)  # "x = 3, y = 3.14"
filename = sprintf("data_%03d.txt", 7)      # "data_007.txt"

文件 I/O 函数

TianYuan 支持基本的文件读写操作,API 与 Matlab/C 标准库兼容。

函数说明
fopen(filename, mode)打开文件,返回文件句柄 fid(≥3)
fclose(fid)关闭文件
fprintf(fid, fmt, ...)格式化写入文件(fid=1 为 stdout)
fgetl(fid)读一行(不含换行符),EOF 返回 -1
fgets(fid)读一行(含换行符),EOF 返回 -1
feof(fid)到达文件末尾时返回 1
load(filename)读取纯文本矩阵文件,返回矩阵
save(filename, varname)将矩阵变量保存为文本文件

fopen 打开模式

  • "r":只读
  • "w":只写(覆盖)
  • "a":追加写

写文件示例

% 写入文本文件
fid = fopen("output.txt", "w")
fprintf(fid, "Hello, File!\n")
fprintf(fid, "x = %d, y = %.4f\n", 42, 3.14)
fclose(fid)

读文件示例

% 逐行读取文件
fid = fopen("input.txt", "r")
while !feof(fid)
    line = fgetl(fid)
    if line == -1
        break
    end
    disp(line)
end
fclose(fid)

load / save 矩阵文件

% 保存矩阵到文件
A = [1 2 3; 4 5 6; 7 8 9]
save("matrix.txt", "A")

# 从文件读取矩阵(文件中每行空白分隔数字,# 或 % 行为注释)
B = load("matrix.txt")
disp(B)

文件句柄 1 和 2 分别对应 stdout(标准输出)和 stderr(标准错误),无需 fopen。析构时所有未关闭的文件句柄会自动关闭。

工作空间管理

clear - 清除变量

语法 说明
clear() 清除所有变量
clear('varname') 清除指定变量

示例

# 创建一些变量
x = 10
y = 20
z = 30

# 清除单个变量
clear('x')
# 现在 x 未定义,y 和 z 仍存在

# 清除所有变量
clear()
# 现在所有变量都被清除

# 脚本开始时清除变量
clear()
clc()
disp('开始新的计算...')

# 清除大型矩阵释放内存
A = rand(1000, 1000)
# ... 使用 A ...
clear('A')
# A 占用的内存被释放

clc - 清空控制台

语法 说明
clc() 清空控制台输出

示例

# 清空屏幕
clc()

# 通常在脚本开头使用
clear()     # 清除变量
clc()       # 清空屏幕
disp('程序开始')

# 在循环中定期清屏
for i = 1:10
    if mod(i, 5) == 0
        clc()
        disp(['已完成 ', num2str(i), ' 次迭代'])
    end
end

方程求解函数

roots - 多项式求根

语法 说明
roots(p) 计算多项式的所有根

参数说明

  • p: 多项式系数向量,从高次到低次
  • 例如: [1, -3, 2] 表示 x² - 3x + 2
  • 返回值: 包含所有根的向量

示例

# 求解二次方程 x^2 - 5x + 6 = 0
# (x - 2)(x - 3) = 0
p = [1, -5, 6]
r = roots(p)
disp('方程的根:')
disp(r)                    # [2, 3]

# 三次方程 x^3 - 6x^2 + 11x - 6 = 0
# (x-1)(x-2)(x-3) = 0
p = [1, -6, 11, -6]
r = roots(p)
disp('三次方程的根:')
disp(r)                    # [1, 2, 3]

# 验证根
p = [1, 0, -1]            # x^2 - 1 = 0
r = roots(p)
disp('x^2 - 1 = 0 的根:')
disp(r)                    # [-1, 1]

# 高次多项式
# x^4 - 10x^2 + 9 = 0
p = [1, 0, -10, 0, 9]
r = roots(p)
disp('x^4 - 10x^2 + 9 = 0 的根:')
disp(r)

# 应用:找临界点
# 已知 f(x) = x^3 - 3x^2 + 2
# f'(x) = 3x^2 - 6x = 0
df = [3, -6, 0]
critical_points = roots(df)
disp('临界点:')
disp(critical_points)

solve - 符号方程求解

限制:TianYuan 目前仅支持数值求解,不支持符号计算。 syms 仅用于声明变量名,solve 仅支持一次和二次多项式方程。 对于其他方程类型,请使用 roots(多项式)或数值迭代方法。

语法 说明
solve(expr, var) 求解符号方程

参数说明

  • expr: 符号表达式(需要先用 syms 声明变量)
  • var: 要求解的变量
  • 返回值: 方程的解

示例

# 声明符号变量
syms('x')

# 求解简单方程 2x + 5 = 0
sol = solve(2*x + 5, x)
disp('2x + 5 = 0 的解:')
disp(sol)                   # x = -2.5

# 二次方程
syms('x')
sol = solve(x^2 - 4, x)
disp('x^2 - 4 = 0 的解:')
disp(sol)

# 三角方程
syms('x')
sol = solve(sin(x), x)
disp('sin(x) = 0 的解:')
disp(sol)

# 指数方程
syms('x')
sol = solve(exp(x) - 5, x)
disp('e^x - 5 = 0 的解:')
disp(sol)

syms - 声明符号变量

语法 说明
syms('varname') 声明符号变量

示例

# 声明单个符号变量
syms('x')

# 使用符号变量构建表达式
expr = x^2 + 2*x + 1

# 求解
sol = solve(expr, x)
disp(sol)

# 声明多个符号变量
syms('x')
syms('y')
syms('z')

# 符号计算
result = x + y + z

mldivide - 线性系统求解(矩阵左除)

语法 说明
x = mldivide(A, b) 求解线性方程组 Ax = b
x = A \ b 等价的运算符形式

参数说明

  • A: 系数矩阵(m×n)
  • b: 右侧向量(m×1)
  • 返回值: 解向量 x(n×1)
  • 比 inv(A)*b 更高效和数值稳定

示例

# 求解线性方程组
# 2x + 3y = 8
# 4x - y = 2
A = [2 3; 4 -1]
b = [8; 2]
x = mldivide(A, b)        # 或 x = A \ b
disp('方程组的解:')
disp(x)

# 验证解
result = A * x
disp('验证 Ax:')
disp(result)
disp('应该等于 b:')
disp(b)

# 更大的线性系统
n = 5
A = rand(n, n)
x_true = rand(n, 1)
b = A * x_true            # 构造右侧
x_solved = mldivide(A, b)
error = norm(x_solved - x_true)
disp(['求解误差: ', num2str(error)])

# 超定系统(最小二乘解)
# 更多方程than未知数
A = [1 1; 1 2; 1 3]       # 3个方程
b = [2; 3; 4]             # 2个未知数
x_ls = mldivide(A, b)
disp('最小二乘解:')
disp(x_ls)

# 与直接求逆比较
A = [2 1; 1 3]
b = [5; 8]
x1 = mldivide(A, b)       # 推荐方法
x2 = inv(A) * b           # 不推荐,效率低且不稳定
disp('mldivide 结果:')
disp(x1)
disp('inv(A)*b 结果:')
disp(x2)

ode45 - 常微分方程求解

语法 说明
ode45(f, tspan, y0) 使用 Runge-Kutta 方法求解 ODE

参数说明

  • f: 函数句柄 dy/dt = f(t, y)
  • tspan: 时间范围向量 [t0, t1, ..., tn]
  • y0: 初始条件
  • 返回值: [t, y] 时间和解的向量

示例

# 简单的一阶 ODE: dy/dt = -y, y(0) = 1
# 解析解: y = e^(-t)
function dydt = odefun(t, y)
    dydt = -y
end

tspan = linspace(0, 5, 50)
y0 = 1
[t, y] = ode45(@odefun, tspan, y0)

# 绘制数值解和解析解
plot(t, y, 'bo-')
hold('on')
y_exact = exp(-t)
plot(t, y_exact, 'r-')
legend(['数值解', '解析解'])
xlabel('时间 t')
ylabel('y(t)')
title('dy/dt = -y 的数值解')
grid('on')

# 指数增长: dy/dt = ky, y(0) = y0
function dydt = growth(t, y)
    k = 0.5
    dydt = k * y
end

tspan = 0:0.1:10
y0 = 1
[t, y] = ode45(@growth, tspan, y0)
plot(t, y)
xlabel('时间')
ylabel('数量')
title('指数增长模型')

# 简谐振子: d²x/dt² + ω²x = 0
# 转换为一阶系统: dx/dt = v, dv/dt = -ω²x
function dydt = harmonic(t, y)
    omega = 2*pi
    x = y(1)
    v = y(2)
    dydt = [v; -omega^2 * x]
end

tspan = linspace(0, 2, 100)
y0 = [1; 0]               # x(0) = 1, v(0) = 0
[t, y] = ode45(@harmonic, tspan, y0)

figure(1)
plot(t, y(:, 1))          # 位置 vs 时间
xlabel('时间')
ylabel('位置')
title('简谐振子')
grid('on')

figure(2)
plot(y(:, 1), y(:, 2))    # 相图
xlabel('位置')
ylabel('速度')
title('相空间轨迹')
grid('on')

# Logistic 增长模型: dy/dt = ry(1 - y/K)
function dydt = logistic(t, y)
    r = 1.5
    K = 100
    dydt = r * y * (1 - y / K)
end

tspan = 0:0.1:10
y0 = 10
[t, y] = ode45(@logistic, tspan, y0)
plot(t, y)
xlabel('时间')
ylabel('种群数量')
title('Logistic 增长模型')
grid('on')

# 阻尼振子: d²x/dt² + 2γdx/dt + ω₀²x = 0
function dydt = damped_oscillator(t, y)
    gamma = 0.5           # 阻尼系数
    omega0 = 2*pi         # 固有频率
    x = y(1)
    v = y(2)
    dydt = [v; -2*gamma*v - omega0^2*x]
end

tspan = linspace(0, 5, 200)
y0 = [1; 0]
[t, y] = ode45(@damped_oscillator, tspan, y0)
plot(t, y(:, 1))
xlabel('时间')
ylabel('位移')
title('阻尼振子')
grid('on')

统计与数组操作函数

这些函数提供丰富的向量/矩阵统计运算与数组重排操作,与 MATLAB 语义兼容。

函数说明
find(A)返回 A 中非零元素的线性下标
any(A)若 A 中任意元素非零则返回 1
all(A)若 A 中所有元素非零则返回 1
prod(A)各元素之积(列方向)
cumsum(A)累积和
cumprod(A)累积积
diff(A)相邻元素之差
var(A)方差(除以 n-1)
std(A)标准差(除以 n-1)
median(A)中位数
mode(A)众数(出现频率最高的值)
cov(A)协方差矩阵
corrcoef(A)相关系数矩阵
repmat(A, m, n)将 A 重复排列为 m×n 块
repelem(A, n)将每个元素重复 n 次
cat(dim, A, B)沿指定维度拼接数组
kron(A, B)Kronecker 积
triu(A)上三角部分
tril(A)下三角部分
circshift(A, n)循环移位
sub2ind(sz, r, c)下标转线性索引
ind2sub(sz, idx)线性索引转下标
unique(A)返回唯一元素(已排序)
ismember(a, B)判断 a 的元素是否属于 B
intersect(A, B)交集
union(A, B)并集
setdiff(A, B)差集(A 中有但 B 中没有)

示例

v = [3 1 4 1 5 9 2 6]
disp(find(v > 4))          # 非零位置: [5 6 8]
disp(cumsum(v))            # 累积和
disp(var(v))               # 方差
disp(median(v))            # 中位数: 3.5
disp(unique(v))            # 去重排序: [1 2 3 4 5 6 9]

A = [1 2; 3 4]
disp(repmat(A, 1, 2))      # 横向重复: [1 2 1 2; 3 4 3 4]
disp(triu(A))              # 上三角: [1 2; 0 4]
disp(circshift(v, 2))      # 向右循环移 2 位

Cell 与数值转换函数

这些函数用于在 Cell 数组与数值矩阵之间转换,以及对 Cell/数组逐元素应用函数。

函数说明
cellfun(f, C)对 Cell 数组 C 的每个元素应用函数 f,返回数值数组
arrayfun(f, A)对数值数组 A 的每个元素应用函数 f
cell2mat(C)将同类 Cell 数组转为数值矩阵
num2cell(A)将数值矩阵转为 Cell 数组

示例

C = {1, 4, 9, 16}
lens = cellfun(@sqrt, C)   # [1 2 3 4]

A = [1 2 3 4]
B = arrayfun(@(x) x^2 + 1, A)   # [2 5 10 17]

M = cell2mat({[1 2]; [3 4]})     # 2×2 矩阵
NC = num2cell([10 20; 30 40])    # 2×2 Cell 数组

高级字符串函数

以下函数在基础字符串操作之上提供分割/拼接、模式匹配、格式解析等能力。

函数说明
strsplit(s)按空白拆分字符串,返回 Cell 数组
strsplit(s, d)按分隔符 d 拆分字符串
strjoin(C)用空格将 Cell 字符串数组合并
strjoin(C, d)用分隔符 d 合并 Cell 字符串数组
contains(s, p)判断 s 是否包含子串 p,返回 0/1
startsWith(s, p)判断 s 是否以 p 开头
endsWith(s, p)判断 s 是否以 p 结尾
regexp(s, pat)正则匹配,返回首个匹配起始位置
regexprep(s, pat, rep)正则替换
sscanf(s, fmt)按格式解析字符串,返回数值向量
int2str(x)数值取整后转字符串
char(n)将 ASCII 码转为字符
erase(s, p)删除 s 中所有 p 出现
pad(s, n)用空格将字符串填充到长度 n

示例

parts = strsplit('a,b,c', ',')    # {'a','b','c'}
s = strjoin(parts, '-')           # 'a-b-c'
disp(contains('hello world', 'world'))   # 1
disp(startsWith('TianYuan', 'Tian'))     # 1

m = regexp('abc123def', '\d+')    # 4  (第一个数字起始位置)
s2 = regexprep('foo BAR foo', 'foo', 'baz')  # 'baz BAR baz'

vals = sscanf('3.14 2.71', '%f')  # [3.14; 2.71]
disp(char(65))                    # 'A'
disp(erase('hello world', 'o'))   # 'hell wrld'

高级矩阵函数

这些函数提供广义逆、矩阵函数(指数/对数/平方根)等高级线性代数运算。

函数说明
pinv(A)Moore-Penrose 伪逆
null(A)零空间的正交基(列向量)
orth(A)列空间的正交基
lsqminnorm(A, b)最小范数最小二乘解
expm(A)矩阵指数 e^A
logm(A)矩阵对数
sqrtm(A)矩阵平方根(满足 X*X = A)

示例

A = [1 2; 3 4; 5 6]
P = pinv(A)                # 3×2 矩阵的伪逆 (2×3)
x = P * [1; 2; 3]         # 最小范数解

B = [1 0; 0 2]
disp(expm(B))              # diag([e^1, e^2])
disp(sqrtm(B))             # diag([1, sqrt(2)])

N = null([1 2 3])          # 零空间基

多项式、优化与积分函数

这些函数覆盖多项式拟合与求值、卷积/反卷积、单变量零点与极值搜索、数值积分以及插值。

函数说明
polyfit(x, y, n)n 次多项式最小二乘拟合,返回系数向量
polyval(p, x)计算多项式在 x 处的值
polyder(p)多项式求导
polyint(p)多项式求积分(常数项为 0)
conv(a, b)多项式相乘(卷积)
deconv(a, b)多项式相除(反卷积)
fzero(f, x0)求函数 f 在 x0 附近的零点
fminbnd(f, a, b)在区间 [a,b] 内求函数极小值
fminsearch(f, x0)无梯度多维极小值(Nelder-Mead)
integral(f, a, b)自适应数值积分 ∫[a,b] f(x) dx
integral2(f, xa, xb, ya, yb)二重数值积分
interp1(x, y, xi)一维线性插值
interp2(X, Y, Z, Xi, Yi)二维插值

示例

x = 0:0.1:2*pi
y = sin(x) + 0.1*randn(size(x))
p = polyfit(x, y, 5)          # 5次拟合
y_fit = polyval(p, x)

root = fzero(@(x) x^3 - x - 2, 1.5)   # 约 1.5214
I = integral(@(x) sin(x), 0, pi)       # 约 2.0

xi = 0:0.05:2*pi
yi = interp1(x, y, xi)        # 插值加密

信号处理与统计分布函数

FFT/IFFT 族函数用于频域分析;统计分布函数提供常用概率分布的 PDF、CDF 与逆 CDF。

函数说明
fft(x)一维快速傅里叶变换
ifft(x)一维快速傅里叶逆变换
fft2(A)二维 FFT
ifft2(A)二维 IFFT
fftshift(x)将零频分量移至中心
normpdf(x, mu, sigma)正态分布概率密度
normcdf(x, mu, sigma)正态分布累积分布函数
norminv(p, mu, sigma)正态分布逆 CDF(分位数)
poisspdf(k, lambda)泊松分布 PMF
poisscdf(k, lambda)泊松分布 CDF
exppdf(x, mu)指数分布 PDF
expcdf(x, mu)指数分布 CDF
unifpdf(x, a, b)均匀分布 PDF
unifcdf(x, a, b)均匀分布 CDF
binopdf(k, n, p)二项分布 PMF
binocdf(k, n, p)二项分布 CDF

示例

# FFT 示例:检测正弦频率
Fs = 1000; t = 0:1/Fs:1-1/Fs
x = sin(2*pi*50*t) + 0.5*sin(2*pi*120*t)
X = fft(x)
f = (0:length(X)-1) * Fs / length(X)
plot(f(1:500), abs(X(1:500)))
xlabel('频率 (Hz)'); title('频谱')

# 统计分布示例
x = -3:0.1:3
y = normpdf(x, 0, 1)          # 标准正态 PDF
disp(normcdf(1.96, 0, 1))     # 约 0.975
disp(norminv(0.975, 0, 1))    # 约 1.96
disp(binopdf(3, 10, 0.5))     # P(X=3), X~B(10,0.5)

扩展文件 I/O 函数

在基础 fopen/fclose/fprintf 之外,TianYuan 还支持二进制读写、文件定位以及 CSV/textscan 高级解析。

函数说明
fseek(fid, off, orig)移动文件指针(orig: -1=头, 0=当前, 1=尾)
ftell(fid)返回当前文件指针位置(字节)
frewind(fid)将文件指针移到开头
fflush(fid)刷新文件缓冲区
fread(fid, n)读取 n 个字节,返回数值向量
fwrite(fid, data)将数值向量以字节流写入文件
csvread(file)读取 CSV 文件为数值矩阵
csvread(file, r, c)从第 r 行 c 列开始读取(0-based)
csvwrite(file, M)将矩阵 M 写入 CSV 文件
textscan(fid, fmt)按格式字符串解析文件,返回 Cell 数组
textscan(fid, fmt, N)最多解析 N 条记录

示例

# 写入并读回 CSV
M = [1.0 2.0 3.0; 4.0 5.0 6.0]
csvwrite('data.csv', M)
M2 = csvread('data.csv')
disp(M2)

# 二进制读写
fid = fopen('bin.dat', 'w')
fwrite(fid, [1 2 3 4 5])
fclose(fid)

fid = fopen('bin.dat', 'r')
v = fread(fid, 5)
fclose(fid)
disp(v)

# textscan 解析带标签的文本
fid = fopen('scores.txt', 'r')
C = textscan(fid, '%s %f')
fclose(fid)
names = C{1}
scores = C{2}

系统与环境函数

这些函数用于查询工作空间和文件系统状态、获取用户输入以及调用系统命令。

函数说明
exist(name)检查变量/文件是否存在,返回类型码(0=不存在)
exist(name, type)按类型检查('var'、'file' 等)
dir()列出当前目录内容,返回结构体数组
dir(path)列出指定路径内容
input(prompt)显示提示并读取用户输入的数值
input(prompt, 's')读取用户输入的字符串
system(cmd)执行系统命令,返回退出码
[s, out] = system(cmd)同时返回退出码和命令输出字符串

示例

# 检查变量是否存在
x = 42
if exist('x')
    disp('x 存在')
end

# 列出目录
entries = dir('.')
for i = 1:length(entries)
    fprintf('%s\n', entries(i).name)
end

# 读取用户输入
n = input('请输入样本数量: ')
name = input('请输入名称: ', 's')

# 执行系统命令
[status, output] = system('date')
fprintf('当前时间: %s\n', output)

计时与调试函数

tic/toc 用于精确计时;assert 和 warning 用于条件检查与调试信息输出。

函数说明
tic()启动计时器
toc()返回自上次 tic 以来的秒数
assert(cond)若 cond 为假则抛出错误
assert(cond, msg)若 cond 为假则以 msg 为错误信息抛出错误
assert(A, B, tol)断言 A 与 B 的差不超过容差 tol
warning(msg)输出警告信息(不中断执行)
warning(id, msg)输出带标识符的警告信息

示例

tic()
A = rand(500, 500)
B = A * A'
elapsed = toc()
fprintf('矩阵乘法耗时: %.4f 秒\n', elapsed)

# 断言测试
x = sqrt(4)
assert(x == 2, 'sqrt(4) 应等于 2')
assert(abs(x - 2) < 1e-10, 'sqrt(4) 数值误差过大')

# 带容差的断言
assert(pi, 3.14159, 1e-4)

# 警告
if elapsed > 1.0
    warning('myPkg:slow', '计算耗时超过 1 秒')
end

类型检测函数

classisa 用于在运行时查询变量的数据类型,便于编写通用函数。

函数说明
class(x)返回 x 的类型字符串,如 'double'、'char'、'cell'、'struct'
isa(x, type)若 x 的类型与 type 匹配则返回 1,否则返回 0

示例

disp(class(3.14))        # 'double'
disp(class('hello'))     # 'char'
disp(class({1,2,3}))     # 'cell'
disp(class(struct('a',1)))  # 'struct'

disp(isa(42, 'double'))  # 1
disp(isa('hi', 'char'))  # 1
disp(isa(42, 'char'))    # 0

# 在函数中做类型分发
function process(x)
    if isa(x, 'char')
        fprintf('字符串输入: %s\n', x)
    elseif isa(x, 'double')
        fprintf('数值输入, 均值=%.4f\n', mean(x))
    else
        warning('未知类型: %s', class(x))
    end
end

动态执行函数

evalfeval 允许在运行时动态执行代码字符串或按名称调用函数。

函数说明
eval(expr)将字符串 expr 作为 TianYuan 代码执行
eval(expr, catchExpr)执行 expr,若出错则执行 catchExpr
feval(fname, arg1, ...)按函数名字符串调用函数,等价于直接调用

示例

# eval 动态执行
eval('x = 100')
disp(x)                        # 100

eval('y = sqrt(x)', 'y = 0')  # 若出错则 y=0
disp(y)

# 动态生成变量名
for i = 1:3
    eval(['v', num2str(i), ' = i^2'])
end
disp(v1); disp(v2); disp(v3)  # 1 4 9

# feval 按名称调用
fname = 'sin'
result = feval(fname, pi/2)    # 1.0
disp(result)

# 函数名由参数决定
ops = {'sin', 'cos', 'exp'}
for i = 1:3
    y = feval(ops{i}, 1.0)
    fprintf('%s(1) = %.4f\n', ops{i}, y)
end

综合应用示例

示例1:数值实验报告生成

# 自动生成实验报告
clc()
clear()

disp('========================================')
disp('         数值实验报告')
disp('========================================')
disp(' ')

# 实验参数
n = 100
iterations = 50
tolerance = 1e-6

fprintf('实验参数:\n')
fprintf('  样本数量: %d\n', n)
fprintf('  迭代次数: %d\n', iterations)
fprintf('  收敛容差: %.2e\n', tolerance)
disp(' ')

# 生成数据
data = randn(n, 1)

# 统计分析
mean_val = mean(data)
max_val = max(data)
min_val = min(data)

fprintf('统计结果:\n')
fprintf('  均值: %.4f\n', mean_val)
fprintf('  最大值: %.4f\n', max_val)
fprintf('  最小值: %.4f\n', min_val)
disp(' ')

disp('实验完成!')
disp('========================================')

示例2:多项式拟合和评估

# 生成带噪声的数据
x = linspace(0, 10, 50)'
y_true = 2*x.^2 - 3*x + 1
noise = 5 * randn(size(x))
y = y_true + noise

# 使用最小二乘法拟合二次多项式
# y = a*x^2 + b*x + c
X = [x.^2, x, ones(size(x))]
coeffs = mldivide(X, y)     # 最小二乘解

a = coeffs(1)
b = coeffs(2)
c = coeffs(3)

fprintf('拟合的多项式: y = %.2fx^2 + %.2fx + %.2f\n', a, b, c)
fprintf('真实的多项式: y = 2.00x^2 - 3.00x + 1.00\n')

# 绘制结果
y_fit = X * coeffs
plot(x, y, 'bo')
hold('on')
plot(x, y_fit, 'r-')
plot(x, y_true, 'g--')
legend(['带噪声数据', '拟合曲线', '真实曲线'])
xlabel('x')
ylabel('y')
title('多项式拟合')
grid('on')
hold('off')

# 计算拟合误差
residuals = y - y_fit
rmse = sqrt(mean(residuals.^2))
fprintf('均方根误差 (RMSE): %.4f\n', rmse)

示例3:交互式数据分析

# 数据分析流程
clear()
clc()

disp('开始数据分析...')
disp(' ')

# 加载数据(模拟)
n_samples = 1000
data = randn(n_samples, 1) * 10 + 50  # 均值50,标准差10

# 描述性统计
disp('描述性统计:')
fprintf('  样本数量: %d\n', length(data))
fprintf('  均值: %.2f\n', mean(data))
fprintf('  最大值: %.2f\n', max(data))
fprintf('  最小值: %.2f\n', min(data))
disp(' ')

# 异常值检测(简单方法)
mean_val = mean(data)
threshold = 30
outliers = abs(data - mean_val) > threshold
n_outliers = sum(outliers)
fprintf('异常值数量: %d (%.1f%%)\n', n_outliers, n_outliers/n_samples*100)
disp(' ')

# 可视化
figure(1)
plot(1:n_samples, data, 'b.')
xlabel('样本索引')
ylabel('数值')
title(['数据分布 (n = ', num2str(n_samples), ')'])
grid('on')

# 直方图(近似)
figure(2)
n_bins = 20
hist_data = floor((data - min(data)) / (max(data) - min(data)) * (n_bins - 1)) + 1
# 简化的直方图显示
disp('数据分析完成!')

示例4:数值积分验证

# 使用梯形法则计算定积分,与解析解比较
clear()
clc()

disp('数值积分验证')
disp(' ')

# 积分 ∫[0, π] sin(x) dx = 2
a = 0
b = pi

# 不同的步长
step_sizes = [0.1, 0.01, 0.001]
analytical = 2

fprintf('积分: ∫[0, π] sin(x) dx\n')
fprintf('解析解: %.10f\n\n', analytical)

fprintf('步长\t\t数值解\t\t\t误差\n')
fprintf('---------------------------------------------------\n')

for i = 1:length(step_sizes)
    h = step_sizes(i)
    x = a:h:b
    y = sin(x)

    # 梯形法则
    integral = h * (sum(y) - (y(1) + y(end)) / 2)
    error = abs(integral - analytical)

    fprintf('%.4f\t\t%.10f\t\t%.2e\n', h, integral, error)
end

示例5:迭代算法进度监控

# 牛顿法求平方根,带进度显示
function y = sqrt_newton(x, tol, max_iter)
    # 初始猜测
    y = x / 2

    disp(['计算 sqrt(', num2str(x), ')'])
    disp(' ')
    fprintf('迭代\t\t估计值\t\t\t误差\n')
    fprintf('---------------------------------------------------\n')

    for iter = 1:max_iter
        y_new = 0.5 * (y + x / y)
        error = abs(y_new - y)

        fprintf('%d\t\t%.10f\t\t%.2e\n', iter, y_new, error)

        if error < tol
            fprintf('\n收敛! 最终结果: %.10f\n', y_new)
            fprintf('实际值: %.10f\n', sqrt(x))
            y = y_new
            return
        end

        y = y_new
    end

    disp(' ')
    disp('警告: 未在最大迭代次数内收敛')
end

# 调用
result = sqrt_newton(2, 1e-10, 20)

注意事项

输出函数

  • disp 用于简单输出,fprintf 用于格式化输出
  • fprintf 的格式字符串必须正确匹配参数类型
  • 字符串拼接使用方括号:['str1', 'str2']
  • 数值必须用 num2str 转换后才能与字符串拼接

方程求解

  • roots 适用于多项式,系数按降幂排列
  • solve 需要先用 syms 声明符号变量
  • mldivide (A\b) 比 inv(A)*b 更高效和稳定
  • ode45 使用自适应步长,适合非刚性 ODE

数值稳定性

  • 避免直接计算矩阵逆,使用 mldivide
  • 检查病态矩阵(大条件数)
  • ODE 求解时注意刚性问题
  • 多项式高次时可能数值不稳定

工作空间管理

  • 在长脚本开始使用 clear()clc()
  • 及时清除大型变量释放内存
  • clear('var') 只清除指定变量
  • 函数内的局部变量自动清除

调试技巧

  • 使用 disp 输出中间结果
  • 使用 fprintf 格式化调试信息
  • 在关键位置输出变量维度:disp(size(A))
  • 使用 assert 进行单元测试和前置条件检查
  • 使用 tic/toc 对热点代码进行性能计时

ODE 求解最佳实践

  • 将高阶 ODE 转换为一阶系统
  • 合理选择时间步长和范围
  • 检查解的物理合理性
  • 对于刚性问题考虑其他求解器

动态执行注意事项

  • eval 会降低代码可读性,应尽量避免;优先使用结构体或 Cell 数组
  • 使用 eval(expr, catchExpr) 捕获潜在运行时错误
  • feval 适合函数名由参数决定的场景,性能与直接调用相同