当前位置: 首页 > article >正文

[paddle] 矩阵的分解

特征值

A A A 是一个 n × n n \times n n×n 的方阵, λ \lambda λ 是一个标量, v \mathbf{v} v 是一个非零向量。如果满足以下方程:
A v = λ v A\mathbf{v} = \lambda\mathbf{v} Av=λv
则称 λ \lambda λ 为矩阵 A A A 的一个 特征值(Eigenvalue),而 v \mathbf{v} v 称为对应于 特征值 λ \lambda λ 的特征向量(Eigenvector)。 行列式 ∣ A − λ I ∣ = 0 |A-\lambda I|=0 AλI=0

paddle.linalg.eigvals(x, name=None) 一般方阵

paddle.linalg.eigvalsh(x, name=None) 实对称或厄尔米特矩阵

import paddle
paddle.seed(2023)
x = paddle.rand(shape=[3, 3], dtype='float64')
print(x)
print(paddle.linalg.eigvals(x))

特征分解

如果矩阵 A A A n n n 个线性独立的特征向量 v 1 , v 2 , … , v n \mathbf{v}_1, \mathbf{v}_2, \ldots, \mathbf{v}_n v1,v2,,vn,分别对应于特征值 λ 1 , λ 2 , … , λ n \lambda_1, \lambda_2, \ldots, \lambda_n λ1,λ2,,λn,那么矩阵 A A A 可以被分解为:
A = V Λ V − 1 A = V \Lambda V^{-1} A=VΛV1
其中:

  • V V V 是一个 n × n n \times n n×n 的矩阵,其列向量是 A A A 的特征向量,即 V = [ v 1 , v 2 , … , v n ] V = [\mathbf{v}_1, \mathbf{v}_2, \ldots, \mathbf{v}_n] V=[v1,v2,,vn]
  • Λ \Lambda Λ 是一个 n × n n \times n n×n 的对角矩阵,其对角线上的元素是 A A A 的特征值,即 Λ = diag ( λ 1 , λ 2 , … , λ n ) \Lambda = \text{diag}(\lambda_1, \lambda_2, \ldots, \lambda_n) Λ=diag(λ1,λ2,,λn)
  • V − 1 V^{-1} V1 是矩阵 V V V 的逆矩阵。

特征分解的性质

  1. 特征值的唯一性:对于一个给定的矩阵,其特征值是唯一的(考虑重根的情况)。
  2. 特征向量的线性独立性:不同特征值对应的特征向量是线性独立的。
  3. 对角化现实中存在大量方阵不能与对角矩阵相似,(但与其若尔当标准型总相似), 这不妨碍软件求解的特征值和特征向量的正确性。

paddle.linalg.eig(x)

  • x为方阵)

paddle.linalg.eigh(x)

  • x为实对称矩阵或这复数共轭对称矩阵(Hermit 矩阵)
import paddle
x = paddle.to_tensor([[1.6707249, 7.2249975, 6.5045543],[9.956216,  8.749598,  6.066444 ],[4.4251957, 1.7983172, 0.370647 ]])
w, v = paddle.linalg.eig(x)
print(v)
print(w)
# paddle.multi_dot  没有定义复数域矩阵乘法,此处给出作者定义的矩阵乘法进行结果检验
def mat_dot(List):A=List[0]B=List[1]sizeA=A.shape sizeB=B.shapeif len(sizeA)==1 and len(sizeB)==1:if sizeA[0]==sizeB[0]:C= addle.sum(A*B)else:print("矩阵乘法维数不匹配")elif len(sizeA)==1 and len(sizeB)==2:if sizeA[0]==sizeB[1]:C=paddle.zeros([sizeB[1]])for j in range(sizeB[1]):C[j]= addle.sum(A*B[:,j])else:print("矩阵乘法维数不匹配")elif len(sizeA)==2 and len(sizeB)==1:C=paddle.zeros([sizeA[0]])if sizeA[1]==sizeB[0]:for i in range(sizeA[0]):C[i]=paddle.sum(A[i,:]*B)elif len(sizeA)==2 and len(sizeB)==2:C=paddle.zeros([sizeA[0],sizeB[1]])if sizeA[1]==sizeB[0]:for i in range(sizeA[0]):for j in range(sizeB[1]):C[i]=paddle.sum(A[i,:]*B[:,j])return(C)     # 特征向量与特征值的检验比较 Aν v.s. λν
for i in range(3):print(mat_dot([x,v[:,i]]))print(w[i]*v[:,i])

LU 分解

X = L U X=LU X=LU, 其中 L L L 为下三角矩阵, U U U 为上三角矩阵,常用与求解线性方程组的解。

paddle.linalg.lu(x, pivot=True, get_infos=False, name=None)

  • x (Tensor) - 需要进行 LU 分解的输入矩阵 x,x 是维度大于 2 维的矩阵。
  • pivot (bool,可选) - LU 分解时是否进行旋转。若为 True 则执行旋转操作,若为 False 则不执行旋转操作,该选项只在 gpu 下起作用,cpu 下暂不支持为 False,会报错。默认 True。
  • get_infos (bool,可选) - 是否返回分解状态信息,若为 True,则返回分解状态 Tensor,否则不返回。默认 False。
  • name (str,可选) - 具体用法请参见 Name,一般无需设置,默认值为 None。
import paddle
x = paddle.to_tensor([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]).astype('float64')
lu,p,info = paddle.linalg.lu(x, get_infos=True)
print(lu)
print(p)
print(info)
P,L,U = paddle.linalg.lu_unpack(lu,p)
print(P)
print(L)
print(U)
# one can verify : X = P @ L @ U ;

Householder 乘积

Householder变换的乘积

Householder变换可以通过一个向量来定义。设 w \mathbf{w} w 是一个单位向量,即 w ⊤ w = 1 \mathbf{w}^\top \mathbf{w} = 1 ww=1,则Householder变换矩阵 H \mathbf{H} H 可以表示为:
H = I − 2 w w ⊤ \mathbf{H} = \mathbf{I} - 2\mathbf{w}\mathbf{w}^\top H=I2ww其中 I \mathbf{I} I 是单位矩阵。

Householder变换的乘积

当多个Householder变换矩阵相乘时,其结果仍然是一个Householder变换矩阵。具体来说,如果 H 1 , H 2 , … , H k \mathbf{H}_1, \mathbf{H}_2, \ldots, \mathbf{H}_k H1,H2,,Hk 都是Householder变换矩阵,那么它们的乘积 H = H 1 H 2 … H k \mathbf{H} = \mathbf{H}_1\mathbf{H}_2 \ldots \mathbf{H}_k H=H1H2Hk 也是一个Householder变换矩阵。常用于QR分解。

乘积的性质

  • 正交性:每个Householder变换矩阵都是正交矩阵,即 H ⊤ = H − 1 \mathbf{H}^\top = \mathbf{H}^{-1} H=H1。因此,它们的乘积也是正交矩阵。
  • 行列式:Householder变换矩阵的行列式为 − 1 -1 1 1 1 1。因此,多个Householder变换矩阵相乘后,其行列式为 ( − 1 ) k (-1)^k (1)k 1 1 1,其中 k k k 是变换的个数。
  • 反射性:Householder变换矩阵的乘积仍然具有反射性,即它可以将一个向量反射到另一个向量上。

paddle.linalg.householder_product(x, tau, name=None)

import paddle
x = paddle.to_tensor([[-1.1280,  0.9012, -0.0190],[ 0.3699,  2.2133, -1.4792],[ 0.0308,  0.3361, -3.1761],[-0.0726,  0.8245, -0.3812]])
tau = paddle.to_tensor([1.7497, 1.1156, 1.7462])
Q = paddle.linalg.householder_product(x, tau)
print(Q)

QR 分解

计算一个或一批矩阵的正交三角分解,也称 QR 分解(暂不支持反向)。

X = Q R X=QR X=QR, Q Q Q是正交矩阵 Q Q ⊤ = I QQ^\top =I QQ=I, R R R 是上三角矩阵。

paddle.linalg.qr(x, mode=‘reduced’, name=None)

  • Tensor Q,正交三角分解的 Q 正交矩阵,需注意如果 mode = “reduced”,则不返回 Q 矩阵,只返回 R 矩阵。
  • Tensor R,正交三角分解的 R 上三角矩阵。
import paddle
x = paddle.to_tensor([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]]).astype('float64')
q, r = paddle.linalg.qr(x)
print (q)
print (r)
# one can verify : X = Q * R ;

Cholesky 分解

Cholesky分解是用于将一个正定矩阵分解为一个下三角矩阵和其转置的乘积的方法。设 A \mathbf{A} A 是一个 n × n n \times n n×n 的正定矩阵,则存在一个下三角矩阵 L \mathbf{L} L,使得:
A = L L ⊤ \mathbf{A} = \mathbf{L}\mathbf{L}^\top A=LL其中 L ⊤ \mathbf{L}^\top L表示 L \mathbf{L} L 的转置矩阵。

Cholesky分解的性质

  • 唯一性:对于给定的正定矩阵 A \mathbf{A} A,其Cholesky分解是唯一的。
  • 正定性:只有正定矩阵才能进行Cholesky分解。
  • 下三角性:分解得到的矩阵 L \mathbf{L} L 是一个下三角矩阵,即其上三角部分的元素均为零。

Cholesky分解的算法

Cholesky分解的算法通常通过迭代计算下三角矩阵 L \mathbf{L} L 的各个元素。对于 i ≤ j i \leq j ij,有:
l i j = 1 l i i ( a i j − ∑ k = 1 i − 1 l i k l j k ) l_{ij} = \frac{1}{l_{ii}} \left( a_{ij} - \sum_{k=1}^{i-1} l_{ik} l_{jk} \right) lij=lii1(aijk=1i1likljk)其中 l i j l_{ij} lij是矩阵 L \mathbf{L} L的元素, a i j a_{ij} aij是矩阵 A \mathbf{A} A 的元素。

paddle.linalg.cholesky(x, upper=False, name=None)

  • x (Tensor)- 输入变量为多维 Tensor,它的维度应该为 [, M, N],其中为零或更大的批次尺寸,并且最里面的两个维度上的矩阵都应为对称的正定矩阵,支持数据类型为 float32、float64。
  • upper (bool)- 指示是否返回上三角矩阵或下三角矩阵。默认值:False。
import paddle
paddle.seed(2023)a = paddle.rand([3, 3], dtype="float32")
a_t = paddle.transpose(a, [1, 0])
x = paddle.matmul(a, a_t) + 1e-03out = paddle.linalg.cholesky(x, upper=False)
print(out)

SVD 分解

SVD分解的定义

SVD(Singular Value Decomposition,奇异值分解)是线性代数中的一种矩阵分解方法,它将一个矩阵分解为三个矩阵的乘积:一个正交矩阵、一个对角矩阵和一个正交矩阵的转置。具体来说,对于任意一个 m × n m \times n m×n的矩阵 A A A,都可以表示为:
A = U Σ V T A = UΣV^T A=UΣVT
其中:

  • U U U是一个 m × m m \times m m×m的正交矩阵,其列向量称为左奇异向量。
  • Σ Σ Σ是一个 m × n m \times n m×n的对角矩阵,对角线上的元素称为奇异值,按照从大到小的顺序排列。
  • V V V是一个 n × n n \times n n×n的正交矩阵,其列向量称为右奇异向量。

SVD分解的性质

  1. 奇异值是非负的,并且按照从大到小的顺序排列。
  2. 左奇异向量和右奇异向量是正交的。
  3. 原矩阵 A A A的秩等于其非零奇异值的个数。
  4. SVD分解是唯一的,只要奇异值不重复。

SVD分解的几何意义

SVD分解可以看作是将矩阵 A A A的作用分解为三个步骤:

  1. 通过矩阵 V V V将原始空间旋转到一个新的坐标系。
  2. 通过对角矩阵 Σ Σ Σ进行各个方向的缩放。
  3. 通过矩阵 U U U将缩放后的空间旋转到最终的坐标系。
    这种分解方式揭示了矩阵 A A A在几何上的本质作用,即旋转、缩放和再旋转。

paddle.linalg.svd(x, full_matrices=False, name=None)

  • x (Tensor) - 输入的欲进行奇异值分解的一个或一批方阵,类型为 Tensor。 x 的形状应为 [*, M, N],其中 * 为零或更大的批次维度,数据类型支持 float32, float64。
  • full_matrices (bool) - 是否计算完整的 U 和 V 矩阵,类型为 bool 默认为 False。这个参数会影响 U 和 V 生成的 Shape。

返回

  • Tensor U,奇异值分解的 U 矩阵。如果 full_matrics 设置为 False,则 Shape 为 [ ∗ , M , K ] [*, M, K] [,M,K],如果 full_metrices 设置为 True,那么 Shape 为 [ ∗ , M , M ] [*, M, M] [,M,M]。其中 K 为 M 和 N 的最小值。
  • Tensor S,奇异值向量,Shape 为 [ ∗ , K ] [*, K] [,K]
  • Tensor VH,奇异值分解的 VH 矩阵。如果 full_matrics 设置为 False,则 Shape 为 [ ∗ , K , N ] [*, K, N] [,K,N],如果 full_metrices 设置为 True,那么 Shape 为 [ ∗ , N , N ] [*, N, N] [,N,N]。其中 K 为 M 和 N 的最小值。
import paddle
x = paddle.to_tensor([[1.0, 2.0], [1.0, 3.0], [4.0, 6.0]]).astype('float64')
x = x.reshape([3, 2])
u, s, vh = paddle.linalg.svd(x)
print (u)
print (s)
print (vh)

低秩矩阵的SVD分解

paddle.linalg.svd_lowrank(x, q=None, niter=2, M=None, name=None)

  • x (Tensor) - 输入的需要进行奇异值分解的一个或一批方阵,类型为 Tensor。 x 的形状应为 [*, M, N],其中 * 为零或更大的批次维度,数据类型支持 float32, float64。
  • q (int,可选) - 对输入 X
    的秩稍微高估的预估值,默认值为 None,代表预估值取 6。
  • niter (int) - 需要进行的子空间迭代次数。默认值为 2。
  • M (Tensor) - 输入矩阵在 axis=-2 维上的均值,形状应为 [*, 1, N],默认为 None。
import paddle
paddle.seed(2024)
x = paddle.randn((5, 5), dtype='float64')
U, S, V = paddle.linalg.svd_lowrank(x)
print(U)
print(S)
print(V)

相关文章:

[paddle] 矩阵的分解

特征值 设 A A A 是一个 n n n \times n nn 的方阵, λ \lambda λ 是一个标量, v \mathbf{v} v 是一个非零向量。如果满足以下方程: A v λ v A\mathbf{v} \lambda\mathbf{v} Avλv 则称 λ \lambda λ 为矩阵 A A A 的一个 特征值…...

极限的深入探讨:从概念到应用的完整指南

极限的深入探讨:从概念到应用的完整指南 一、历史背景与发展 1. 极限概念的演变 在维尔斯特拉斯(Karl Weierstrass,1815-1897)提出他的严格定义之前,极限概念经历了漫长的发展过程: 古希腊时期&#xf…...

康谋方案 | BEV感知技术:多相机数据采集与高精度时间同步方案

随着自动驾驶技术的快速发展,车辆准确感知周围环境的能力变得至关重要。BEV(Birds-Eye-View,鸟瞰图)感知技术,以其独特的视角和强大的数据处理能力,正成为自动驾驶领域的一大研究热点。 一、BEV感知技术概…...

UE学习日志#23 C++笔记#9 编码风格

注:此文章为学习笔记,只记录个人不熟悉或备忘的内容 1 为代码编写文档 1.1 使用注释的原因 1.说明用途的注释 应该注释的信息:输入,输出含义,参数的类型含义,错误条件和处理,预期用途&#x…...

更换IP属地会影响网络连接速度吗

在数字化时代,网络连接速度对于个人用户和企业来说都至关重要。无论是日常浏览网页、观看视频,还是进行在线办公、游戏娱乐,网络速度都直接影响着我们的体验。而IP属地,作为网络连接中的一个重要元素,其变动是否会引发…...

深入探索 C++17 特征变量模板 (xxx_v)

文章目录 一、C++类型特征的前世今生二、C++17特征变量模板闪亮登场三、常见特征变量模板的实际应用(一)基本类型判断(二)指针与引用判断四、在模板元编程中的关键作用五、总结与展望在C++的持续演进中,C++17带来了许多令人眼前一亮的特性,其中特征变量模板(xxx_v)以其…...

C# 中 Guid类 使用详解

总目录 前言 C# 中的 Guid 类(全局唯一标识符,Globally Unique Identifier)用于生成和操作 128 位的唯一标识符。它在需要唯一标识的场景(如数据库主键、分布式系统等)中广泛使用。 一、什么是 Guid Guid&#xff08…...

生产环境的 MySQL事务隔离级别

MySQL 数据库的默认隔离级别是 RR( 可重复读 ),但是很多大公司把隔离级别改成了 RC(读已提交),主要原因是为了提高并发和降低死锁概率 为了解决幻读的问题 RR 相比 RC 多了间隙锁( gap lock )和临键锁( next-keylock )。而 RC 中修改数据仅用行锁&#…...

无用知识研究:std::initializer_list的秘密

先说结论,用std::initializer_list初始化vector,内部逻辑是先生成了一个临时数组,进行了拷贝构造,然后用这个数组的起终指针初始化initializer_list。然后再用initializer_list对vector进行初始化,这个动作又触发了拷贝…...

web安全:任意文件下载漏洞

背景: 点击对应名字,下载对应图片。但服务器还存在其他文件,只是前端没有展示出来。通过模拟路径下载,可以获取到意想不到的数据。 看点击代码: 如果模拟没有前端的图片,也会发现下载了 所以这个叫任…...

oracle:索引(B树索引,位图索引,分区索引,主键索引,唯一索引,联合索引/组合索引,函数索引)

索引通过存储列的排序值来加快对表中数据的访问速度,帮助数据库系统快速定位到所需数据,避免全表扫描 B树索引(B-Tree Index) B树索引是一种平衡树结构,适合处理范围查询和精确查找。它的设计目标是保持数据有序,并支持高效的插入…...

大模型实战篇之Deepseek二、一键部署DeepSeek-V3和DeepSeek-R1模型

一键部署DeepSeek-V3和DeepSeek-R1模型:3步,0代码! 随着人工智能技术的飞速发展,越来越多的企业和开发者希望将强大的AI模型快速应用到实际业务中。DeepSeek作为一款高性能的语言模型,已经在多个领域展现出巨大的应用潜力。然而,传统的模型部署流程往往复杂且耗时。今天,…...

【CPP】CPP经典面试题

文章目录 引言1. C 基础1.1 C 中的 const 关键字1.2 C 中的 static 关键字 2. 内存管理2.1 C 中的 new 和 delete2.2 内存泄漏 3. 面向对象编程3.1 继承和多态3.2 多重继承 4. 模板和泛型编程4.1 函数模板4.2 类模板 5. STL 和标准库5.1 容器5.2 迭代器 6. 高级特性6.1 移动语义…...

Windows 中学习Docker环境准备2、Docker Desktop中安装ubuntu

Windows 中学习Docker环境准备1、Win11安装Docker Desktop Windows 中学习Docker环境准备2、Docker Desktop中安装ubuntu Windows 中学习Docker环境准备3、在Ubuntu中安装Docker 需要更多Docker学习视频和资料,请文末联系 一、安装 Docker Desktop 下载 Docker…...

C++11详解(三) -- 可变参数模版和lambda

文章目录 1.可变模版参数1.1 基本语法及其原理1.2 包扩展1.3 empalce系列接口1.3.1 push_back和emplace_back1.3.2 emplace_back在list中的使用(模拟实现) 2. lambda2.1 lambda表达式语法 1.可变模版参数 1.1 基本语法及其原理 1. C11支持可变参数模版&…...

网站打开提示不安全

当网站打开时显示“不安全”提示(通常表现为浏览器地址栏中出现“不安全”字样或红色警告图标),这意味着网站未使用有效的SSL证书或HTTPS协议,导致浏览器认为连接不安全。以下是解决这一问题的详细步骤: 一. 原因分析 …...

OpenCV:特征检测总结

目录 一、什么是特征检测? 二、OpenCV 中的常见特征检测方法 1. Harris 角点检测 2. Shi-Tomasi 角点检测 3. Canny 边缘检测 4. SIFT(尺度不变特征变换) 5. ORB 三、特征检测的应用场景 1. 图像匹配 2. 运动检测 3. 自动驾驶 4.…...

标志的推理

下面的讨论是我对《对编程实现拟人智能可行性的论证》这篇文章的“赋值与对象的标志”这一节的展开讨论。 标志能够使我们更好的思维(比如用轮廓标记物体对象,用兴奋强度标记回忆情况等等)。有思维标志、信息标志,单纯标志、组合…...

python学opencv|读取图像(五十七)使用cv2.bilateralFilter()函数实现图像像素双边滤波处理

【1】引言 前序学习过程中,已经掌握了对图像的基本滤波操作技巧,具体的图像滤波方式包括均值滤波、中值滤波和高斯滤波,相关文章链接有: python学opencv|读取图像(五十四)使用cv2.blur()函数实现图像像素…...

【SQL技术】不同数据库引擎 SQL 优化方案剖析

一、引言 在数据处理和分析的世界里,SQL 是不可或缺的工具。不同的数据库系统,如 MySQL、PostgreSQL(PG)、Doris 和 Hive,在架构和性能特点上存在差异,因此针对它们的 SQL 优化策略也各有不同。这些数据库中…...

链式结构二叉树(递归暴力美学)

文章目录 1. 链式结构二叉树1.1 二叉树创建 2. 前中后序遍历2.1 遍历规则2.2 代码实现图文理解 3. 结点个数以及高度等二叉树结点个数正确做法: 4. 层序遍历5. 判断是否完全二叉树 1. 链式结构二叉树 完成了顺序结构二叉树的代码实现,可以知道其底层结构…...

使用类别数据编码进行连续变量的特征提取

在数据科学和机器学习中,数据预处理是模型构建的重要步骤。对于处理结构化数据时,特别是包含类别型数据的场景,类别数据编码是必不可少的步骤。类别数据通常以文字、标签等形式出现,但大多数机器学习算法只能处理数值型数据,因此需要将类别数据转化为数值格式。编码方式的…...

PCL 最小包围圆(二维)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 最小包围圆是指能够包含给定点集中所有点的最小圆。这个算法通常用于计算几何、计算机图形学、机器学习等领域。以下是该算法的基本原理和实现流程: 1. 初始化:将点集中的所有点加入待处理列表。 2. 查找最远点:…...

技术文档管理最佳实践:高效、专业、可持续

文章目录 技术文档管理最佳实践:高效、专业、可持续1. 技术文档的核心价值1.1 降低知识流失风险1.2 提升开发效率1.3 增强团队协作1.4 规范技术资产管理 2. 技术文档分类与规范2.1 代码相关文档2.2 过程与运维文档2.3 知识与培训文档 3. 工具选型:自动化…...

56. Uboot移植实验

一、NXP官方Uboot编译与测试 1、将NXP提供的uboot拷贝到ubuntu中。 一个开发板也好运行uboot,DDR或者叫DRAM,串口,SD、EMMC、NAND。板子能工作。 测似结果: 1、uboot能正常启动 2、LCD驱动要根据所使用的屏幕修改。 3、NET初始…...

AI大模型:本地部署deepseek

一、安装lmstudio 1、下载网站: LM Studio - Discover, download, and run local LLMs 2、直接安装即可,记住安装的路径 二、下载deepseek模型 2.1、下载的流程 1、下载网站 https://huggingface.co/models 2、在搜索框输入:deepseek …...

(算法竞赛)图论+DFS深搜——图的dfs遍历1

题目描述 给定一个无向图,包含 n 个顶点(编号为 1 到 n)和 e 条边。要求从顶点 1 开始进行深度优先搜索(DFS),并按照访问顺序输出遍历结果。注意:当存在多个邻接点时,优先访问编号较…...

RK3588平台开发系列讲解(DMA篇)DMA engine使用

文章目录 一、DMA 使用步骤二、DMA接口2.1、DMA 通道管理相关接口2.2、DMA 描述符相关接口2.3、DMA 启动与控制接口2.4、DMA 状态检查接口2.5、 DMA 缓存管理接口2.6、DMA 中断与同步机制沉淀、分享、成长,让自己和他人都能有所收获!😄 Linux 内核的 DMA 引擎提供了一组完整…...

报名 | IEEE ICME 2025 音频编码器能力挑战赛正式开启

音频编码器是多模态大模型的重要组件,优秀的音频编码器在构建多模态系统中至关重要。在此背景下,小米集团、萨里大学、海天瑞声共同主办了 IEEE International Conference on Multimedia & Expo (ICME) 2025 Audio Encoder Capability Challenge。 …...

fputs的概念和使用案例

fputs 是 C 语言中用于向文件写入字符串的标准库函数。它与 puts 类似,但不会自动添加换行符,且支持向任意文件流(如磁盘文件、标准输出等)写入数据。 概念解析 函数原型:int fputs(const char *str, FILE *stream); …...