快速傅里叶变换(FFT)原理与工程实践:从分治算法到信号处理应用

news2026/5/21 1:04:43
1. 从时域到频域为什么我们需要FFT如果你曾经处理过音频信号、图像数据或者调试过通信系统那你一定对“频谱”这个概念不陌生。我们生活的世界是时间的函数声音随着时间起伏图像像素在空间上排列这些都是时域或空域的表示。但很多时候隐藏在时间波动背后的规律在频域里会变得一目了然——哪些是稳定的基频哪些是恼人的噪声谐波信号的能量集中在哪个频率范围。傅里叶变换就是连接时域和频域的那座桥梁它告诉我们任何一个复杂的波形都可以分解成一系列不同频率、不同幅度、不同相位的正弦波的叠加。然而理论很美好现实却很骨感。传统的离散傅里叶变换DFT计算量巨大。对于一个包含N个采样点的数据序列直接计算其DFT需要进行大约N²次复数乘法和加法运算。当N1024时这就是超过一百万次运算当N增长到数万甚至百万比如高分辨率图像处理或长时间音频分析计算量会变得完全不可接受几乎无法实现实时处理。这就是“快速傅里叶变换”FFT诞生的背景。它不是一种新的变换而是计算DFT的一种极其高效的算法。FFT巧妙利用了DFT运算中复数旋转因子的对称性和周期性将计算复杂度从O(N²)直接降到了O(N log₂ N)。这个提升是指数级的——同样是N1024FFT所需的运算量骤降到约10240次效率提升了两个数量级。可以说没有FFT现代数字信号处理、音频编解码、无线通信乃至医学成像都将寸步难行。2. FFT的核心思想分而治之的智慧FFT算法家族有很多成员最经典、应用最广的是库利-图基Cooley-Tukey算法。它的核心思想是“分治”Divide and Conquer这也是其能达到O(N log₂ N)复杂度的关键。理解这个思想比记住任何蝴蝶图都更重要。2.1 从DFT公式看冗余首先我们回顾一下N点序列x[n]的DFT公式 X[k] Σ_{n0}^{N-1} x[n] * W_N^{nk}, 其中 k 0, 1, ..., N-1。 这里W_N e^{-j2π/N}称为旋转因子Twiddle Factor。直接计算这个公式每个X[k]都需要N次复数乘加总共N个k所以是N²量级。但仔细观察旋转因子W_N^{nk}它具有两个关键性质对称性W_N^{nk} -W_N^{nk N/2}。这意味着有一半的旋转因子是另一半的相反数。周期性W_N^{nk} W_N^{(nN)k} W_N^{n(kN)}。这意味着许多乘法计算是重复的。直接计算DFT时我们重复地计算了大量相同的W_N^{nk}值。FFT的智慧就在于通过巧妙的序列重排和计算重组彻底避免这些重复计算。2.2 库利-图基算法的分治步骤库利-图基算法要求点数N是2的整数次幂即N2^m。如果不是可以通过补零来满足。其分治过程可以概括为三步第一步分解将原始的N点序列x[n]按照序号n的奇偶性拆分成两个长度为N/2的子序列偶数序列x_e[r] x[2r], 其中 r 0, 1, ..., N/2 - 1奇数序列x_o[r] x[2r1], 其中 r 0, 1, ..., N/2 - 1第二步递归求解分别计算这两个N/2点子序列的DFT记作X_e[k]和X_o[k]。这里k的范围也是0到N/2-1。注意计算这两个小规模DFT时我们又可以继续对它们进行奇偶分解直到分解到2点DFT为止。2点DFT的计算非常简单无需任何复数乘法。第三步合并利用旋转因子的性质将两个N/2点DFT的结果组合成最终的N点DFT结果X[k] X[k] X_e[k] W_N^k * X_o[k] X[k N/2] X_e[k] - W_N^k * X_o[k] 其中 k 0, 1, ..., N/2 - 1这个合并公式就是著名的“蝴蝶运算”Butterfly Operation的核心。它告诉我们要得到完整频谱的前半部分k从0到N/2-1和后半部分k从N/2到N-1我们只需要计算N/2个复数乘法和N次复数加法。整个合并过程呈现出蝴蝶状的信号流图这也是“蝶形运算”名称的由来。注意这里的“分解-递归-合并”是典型的分治策略。每一次分解都将问题规模减半而合并的代价是线性的O(N)。根据主定理总复杂度就是O(N log N)。理解这个递归树模型是掌握FFT原理的钥匙。2.3 一个8点FFT的直观示例让我们用N8来具体走一遍这个流程这比任何抽象描述都更直观。第一次分解将8点序列x[0]...x[7]按奇偶分成偶数部分x[0], x[2], x[4], x[6]奇数部分x[1], x[3], x[5], x[7]第二次分解对两个4点序列继续按奇偶分偶数部分的偶数x[0], x[4]偶数部分的奇数x[2], x[6]奇数部分的偶数x[1], x[5]奇数部分的奇数x[3], x[7]计算2点DFT现在我们有4组2点序列。2点DFT计算就是简单的加减法。例如对于{x[0], x[4]}其2点DFT结果是 X‘[0] x[0] x[4] X‘[1] x[0] - x[4] 这里没有复数乘法因为W_2^01 W_2^1-1。逐级合并然后我们开始回溯。用蝴蝶运算公式将4组2点DFT结果合并成2组4点DFT结果再将这2组4点DFT结果合并成最终的8点DFT结果。在这个过程中你会发现输入序列x[n]的序号顺序被打乱了。最终计算流程图中输入的顺序是x[0], x[4], x[2], x[6], x[1], x[5], x[3], x[7]。这个顺序恰好是原始序号0-7的二进制表示000, 001, 010...进行“位反转”Bit-Reversal后的结果。这是基2时域抽取FFT的一个特征为了进行原位计算节省内存输入序列需要先进行位反转重排。3. FFT的两种经典实现时域抽取与频域抽取根据分解的对象是时域序列还是频域结果库利-图基算法主要有两种形式时域抽取法DIT-FFT和频域抽取法DIF-FFT。它们本质上是等价的只是信号流图的走向不同。3.1 时域抽取法Decimation-In-Time, DIT我们上面详细描述的就是DIT-FFT。它的特点是操作对象在时域上对输入序列x[n]按奇偶进行抽取分解。计算流程先对小的子序列进行DFT然后逐级乘以旋转因子并合并蝶形运算。输入顺序需要先对输入序列进行“位反转”重排。输出顺序最终的频域结果X[k]是按自然顺序0, 1, 2, ...输出的。DIT的蝶形运算公式即合并公式为 X_m1[p] X_m[p] W_N^r * X_m[q] X_m1[q] X_m[p] - W_N^r * X_m[q] 其中m表示第几级运算p和q是参与本次蝶形运算的两个节点的序号。3.2 频域抽取法Decimation-In-Frequency, DIFDIF-FFT采取了另一种对称的思路操作对象在频域上对输出序列X[k]按奇偶进行抽取。计算流程先对时域序列进行蝶形运算加减和乘旋转因子然后再对结果序列求更短的DFT。输入顺序输入序列x[n]保持自然顺序。输出顺序最终的频域结果X[k]是“位反转”顺序的如果需要自然顺序则需后处理。DIF的蝶形运算公式为 X_m[p] X_m-1[p] X_m-1[q] X_m[q] (X_m-1[p] - X_m-1[q]) * W_N^r 注意这里旋转因子W_N^r的乘法发生在减法之后这与DIT不同。DIT与DIF的选择数学上等价两者计算量和结果完全一致。实现考量DIT需要输入位反转DIF需要输出位反转。在硬件如FPGA实现时根据数据流的特点可能其中一种更方便。在软件实现中这点差异影响不大。理解层面我个人建议先从DIT入手理解分治思想因为“分解时域序列”更符合我们处理问题的直觉。实操心得在编写FFT代码时无论是DIT还是DIF最关键的是正确实现“蝴蝶运算单元”和旋转因子表Twiddle Factor Table。旋转因子W_N^r cos(2πr/N) - j*sin(2πr/N)可以预先计算好并存储在一个数组中避免在循环中重复计算三角函数这是最重要的性能优化手段之一。4. 从原理到代码手撕一个基2 DIT-FFT理解了原理我们尝试用代码以Python为例实现一个最基础的、非递归的、原位计算的基2 DIT-FFT。这将彻底打通你的任督二脉。4.1 关键步骤拆解数据长度检查与补零确保输入数据长度N是2的幂。如果不是需要补零到最近的2的幂。补零会在频域上增加插值点使频谱看起来更平滑但不增加频率分辨率。位反转重排实现一个函数将数组索引进行二进制位反转。这是DIT-FFT正确计算的前提。预先计算旋转因子表根据总点数N计算所有可能用到的W_N^r存于数组中。分层进行蝶形运算这是核心循环。外层循环遍历每一级stage从1到log2(N)。内层循环遍历当前级的所有蝴蝶组最内层进行具体的蝶形运算。4.2 Python代码实现与逐行解析import numpy as np import matplotlib.pyplot as plt def fft_base2_dit(x): 基2时域抽取FFT实现。 参数 x: 输入的一维复数列表或numpy数组。 返回 与输入等长的复数数组即FFT结果。 x np.asarray(x, dtypenp.complex128) # 确保是复数数组 N x.shape[0] # 1. 检查长度是否为2的幂本示例假设输入已满足 if not (N (N - 1) 0) and N ! 0: raise ValueError(输入长度必须是2的幂。请先补零。) # 2. 位反转重排 (Bit-Reversal Permutation) # 关键技巧通过迭代交换实现复杂度O(N) j 0 for i in range(1, N): bit N 1 # bit是最高位掩码 while j bit: j ^ bit bit 1 j ^ bit if i j: x[i], x[j] x[j], x[i] # 交换位置 # 3. 分层进行蝶形运算 stage 1 while stage N: Wm np.exp(-2j * np.pi / stage) # 当前级旋转因子的基 # 外层遍历当前级的每个蝶形组 for k in range(0, N, 2*stage): w 1 0j # 初始化旋转因子为W_N^0 # 内层遍历一个组内的蝴蝶对 for j in range(stage): # --- 核心蝶形运算 --- t w * x[k j stage] # 乘法旋转因子乘上奇数路径数据 u x[k j] # 偶数路径数据 # 合并 x[k j] u t # 上半部分输出 x[k j stage] u - t # 下半部分输出 # --- 蝶形运算结束 --- w * Wm # 更新旋转因子为下一个W_N^r stage 1 # 进入下一级点数翻倍 return x # 测试生成一个复合正弦信号并分析 fs 1000 # 采样率 1000 Hz T 1.0 # 信号时长 1秒 N 1024 # 采样点数必须是2的幂 t np.linspace(0, T, N, endpointFalse) # 时间向量 # 生成信号50Hz正弦 120Hz正弦 随机噪声 signal 0.7 * np.sin(2 * np.pi * 50 * t) np.sin(2 * np.pi * 120 * t) signal 0.2 * np.random.randn(N) # 加入高斯白噪声 # 计算FFT fft_result fft_base2_dit(signal) # 计算频率轴 freqs np.fft.fftfreq(N, 1/fs) # 取幅度谱只取前一半因为对称 magnitude np.abs(fft_result[:N//2]) * 2 / N # 乘以2/N恢复真实幅度除直流分量 freqs_half freqs[:N//2] # 绘图 plt.figure(figsize(12, 6)) plt.subplot(2, 1, 1) plt.plot(t, signal) plt.title(原始时域信号) plt.xlabel(时间 [秒]) plt.ylabel(幅度) plt.grid() plt.subplot(2, 1, 2) plt.plot(freqs_half, magnitude) plt.title(FFT幅度谱) plt.xlabel(频率 [Hz]) plt.ylabel(幅度) plt.grid() plt.axvline(x50, colorr, linestyle--, alpha0.5, label50 Hz) plt.axvline(x120, colorg, linestyle--, alpha0.5, label120 Hz) plt.legend() plt.tight_layout() plt.show()代码关键点解析位反转循环for i in range(1, N):这个循环实现了O(N)时间复杂度的原位交换。变量j始终跟踪i的位反转值。理解这个算法需要一点二进制操作的技巧它是高效实现的关键。蝶形运算三层循环最外层while stage N:控制计算的“级”数从1点对开始到N/2点对结束。stage同时代表了当前级一个蝶形组的大小。中层for k in range(0, N, 2*stage):遍历当前级的所有蝶形组。k是每个组的起始索引。内层for j in range(stage):遍历一个组内的所有蝴蝶对。j是组内的偏移量。旋转因子更新w * Wm是在内层循环中进行的巧妙地利用了W_N^(r1) W_N^r * W_N^1的性质避免了每次重新计算三角函数这是极大的性能优化。原位计算所有计算都在数组x中完成输入数据被逐步覆盖为中间结果和最终结果节省了大量内存。注意事项自己实现的FFT主要用于教学和理解。在生产环境中务必使用高度优化的库如NumPy的np.fft.fft、SciPy的scipy.fftpack或者Intel的MKL、FFTW等。这些库使用了更高级的算法如混合基、SIMD指令优化、多线程等其性能远超我们的简单实现。5. FFT应用中的核心参数与常见陷阱掌握了算法不等于能正确使用FFT。在实际工程中参数理解和陷阱规避至关重要。5.1 关键参数解析采样率Fs与奈奎斯特频率Fnyquist采样率Fs每秒采集的样本数。它决定了你能分析的最高频率。奈奎斯特频率Fnyquist Fs / 2这是FFT能无混叠地显示的最高频率。任何高于此频率的信号成分都会以“混叠”的形式折叠到0~Fnyquist之间造成频谱失真。因此采样前必须用抗混叠低通滤波器滤除高于Fnyquist的频率分量。点数N与频率分辨率Δf点数N参与FFT计算的数据长度。频率分辨率Δf Fs / N频谱图上相邻两条谱线之间的频率间隔。它决定了你能区分多近的两个频率。想要更高的频率分辨率必须增加N或降低Fs。单纯补零增加N但不增加实际数据并不能提高真正的分辨率只是让频谱曲线看起来更平滑称为“插值”。幅度校正FFT计算出的原始结果是复数其幅度需要经过校正才能反映信号的真实物理幅度。对于非直流分量真实幅度 abs(FFT结果) * 2 / N。对于直流分量0Hz真实幅度 abs(FFT结果) / N。如果使用了窗函数见下文由于窗函数导致信号能量泄露还需要除以窗函数的相干增益Coherent Gain进行补偿例如汉宁窗的补偿系数约为0.5。窗函数Window Function问题FFT默认假设输入信号是无限长周期信号的一个完整周期。如果截取的不是整数个周期就会发生“频谱泄露”Spectral Leakage即能量从主频扩散到旁边的频带上导致频谱拖尾、幅值不准。解决方案在FFT前将时域数据乘以一个窗函数如汉宁窗Hanning、汉明窗Hamming、布莱克曼窗Blackman。窗函数的两端平滑过渡到0减弱截断处的突变从而抑制泄露。代价窗函数会加宽主瓣降低频率分辨率并引入一定的幅值误差。这是一种用分辨率换取频谱纯度的权衡。5.2 常见问题与排查技巧实录在实际调试中FFT频谱图出现异常是家常便饭。下面是一个快速排查指南现象可能原因排查与解决方法频谱出现对称的镜像峰这是正常现象。FFT结果对于实信号是共轭对称的通常只显示前一半0 ~ Fs/2。检查是否错误地绘制了整个频谱。绘图时只取fft_result[:N//2]即可。峰值频率位置有偏差1. 频率分辨率不足。2. 非整数周期截断导致的栅栏效应。1. 增加数据长度N以提高分辨率。2. 使用窗函数或通过峰值插值如抛物线插值来估计真实峰值频率。峰值幅度不准确1. 未进行幅度校正。2. 频谱泄露严重。3. 使用了窗函数但未进行幅度补偿。1. 按公式*2/N进行校正直流分量除外。2. 确保采集整数个周期或使用窗函数。3. 查找所用窗函数的相干增益并进行补偿。频谱底部噪声很高或出现不应有的频率1. 直流偏移DC Offset。2. 工频干扰50/60Hz。3. 谐波失真。4. 量化噪声或电路噪声。1. 对时域信号去均值减去平均值。2. 检查接地使用差分测量或带阻滤波器。3. 检查传感器或放大器的线性度。4. 评估ADC位数优化电路布局。高频部分出现奇怪的折叠频率混叠。输入信号中含有高于Fs/2的频率成分。这是严重错误。必须在ADC采样前使用模拟抗混叠滤波器低通截止频率Fs/2滤除高频成分。计算速度极慢1. 使用了O(N²)的DFT直接计算。2. 点数N不是2的幂导致库函数使用更慢的算法。3. 在循环中重复计算FFT。1. 确认使用FFT算法。2. 将数据长度补零到最近的2的幂。3. 对于固定长度的重复计算考虑使用FFT计划如FFTW的planner或预计算旋转因子。一个典型的调试案例我曾用麦克风采集一段440Hz的纯音但FFT频谱在440Hz附近显示了一个很宽的“山包”而不是尖锐的峰。首先我检查了幅度校正无误。然后我意识到录音时长可能不是440Hz周期的整数倍。查看采样率Fs44100Hz录音点数N8192。那么录音时长T N/Fs ≈ 0.1858秒。440Hz信号的周期约为0.00227秒。0.1858 / 0.00227 ≈ 81.85不是整数。这就是非整数周期截断导致的频谱泄露。我应用了汉宁窗后频谱峰变窄了但幅度降低了。我查表得知汉宁窗的相干增益是0.5于是将幅度谱结果除以0.5最终得到了准确的幅度值。6. 超越基2混合基与实序列FFT优化基2 FFT要求点数是2的幂但实际数据长度未必总能满足。此外对于最常见的实值输入信号标准的复数FFT有一半的计算是冗余的。针对这些情况有更高级的优化。6.1 混合基FFT与补零策略当N不是2的幂时库利-图基算法可以推广到任意复合数N N1 * N2。这就是混合基FFT。例如N100 4 * 25可以先做4点FFT再做25点FFT。高效实现混合基FFT非常复杂通常由专业数学库如FFTW完成。对于普通开发者最实用的策略是补零Zero-Padding做法在时域数据的末尾添加若干个0使总长度达到2的幂。效果满足算法要求使能使用高效的基2 FFT。频谱插值使频域输出点数增加曲线更光滑便于观察峰值和形状。这并没有提高真正的频率分辨率因为分辨率ΔfFs/N_original只由原始数据长度决定。可能引入虚假信息过度补零会在频谱中产生振铃效应类似于加了矩形窗。通常补零到2-4倍原始长度是合理的。6.2 实序列FFT的加速技巧对于实值输入信号x[n]其FFT结果X[k]具有共轭对称性X[k] X*[N-k]。这意味着有一半的信息是冗余的。利用这个性质我们可以将两个实序列打包成一个复序列一次FFT同时算出两者的频谱效率几乎翻倍。打包FFT算法步骤假设有两个实序列a[n]和b[n]长度均为N。构造一个复序列h[n] a[n] j * b[n]。对h[n]执行N点复数FFT得到H[k]。利用共轭对称性可以从H[k]中分离出A[k]a[n]的FFT和B[k]b[n]的FFT A[k] 0.5 * (H[k] H*[N-k]) B[k] -0.5j * (H[k] - H*[N-k]) 其中k0, 1, ..., N-1且H*表示共轭。这样我们只用了一次N点复数FFT计算量约O(N log N)和少量后处理就得到了两个实序列的FFT。如果分别计算需要两次计算量几乎是两倍。这个技巧在需要同时处理多路实信号如立体声音频时非常有用。实操心得在嵌入式或资源受限的环境中如果只需要计算实序列的幅度谱而不关心相位有一个更狠的优化只计算前半部分频谱k从0到N/2。因为对于实信号幅度谱是偶对称的。我们可以利用DCT离散余弦变换的某些变体它本身就是为实序列设计的在某些情况下比FFT更高效。例如JPEG图像压缩中使用的就是DCT。7. FFT在工程中的典型应用场景与选型理解了原理和实现最后来看看FFT如何解决实际问题。它的应用几乎遍布所有工程领域。1. 音频信号处理频谱分析图形均衡器、音频频谱显示器。通过FFT将声音分解成不同频带的能量进行可视化或调节。音高检测通过寻找幅度谱中的峰值频率来识别音符。需要较高的频率分辨率。滤波在频域将特定频段置零如滤除50Hz工频干扰再做逆FFTIFFT变回时域实现滤波。这称为频域滤波。编解码MP3、AAC等音频压缩格式的核心。利用FFT将信号转换到频域利用人耳听觉掩蔽效应去除人耳不敏感的频段成分达到压缩目的。2. 通信系统正交频分复用OFDM4G/5G和Wi-Fi的核心技术。将高速数据流分配到大量正交的子载波上传输每个子载波的调制解调正是通过IFFT/FFT对来实现的。发射端用IFFT将频域数据变为时域信号接收端用FFT恢复频域数据。调制识别与解调通过分析接收信号的频谱特征自动识别其调制方式如FSK, PSK, QAM。信道估计通过发送已知的导频信号在接收端用FFT分析信道在频域的特性频率响应。3. 图像处理二维FFT频域滤波将图像进行二维FFT在频域去除周期性噪声如条纹干扰、实现图像锐化或模糊再通过二维IFFT转回空间域。卷积加速大尺寸卷积核在时域空域计算很慢。利用“时域卷积等于频域相乘”的性质通过FFT将图像和卷积核变换到频域做乘法后再IFFT回来可以极大加速计算。这是许多深度学习框架优化卷积层的手段之一。图像压缩类似音频JPEG压缩先将图像分块做DCT与FFT类似然后量化高频系数。4. 振动分析与故障诊断旋转机械监测对轴承、齿轮箱的振动信号做FFT分析频谱中是否出现故障特征频率如轴承的通过频率实现预测性维护。模态分析通过激励结构和测量响应利用FFT计算系统的频率响应函数FRF识别结构的固有频率、阻尼比和振型。工具与库选型建议Python (科研、原型)numpy.fft/scipy.fft是绝对主流。scipy.fft接口更统一支持更多变换类型。对于实信号使用rfft系列函数如np.fft.rfft效率更高它只计算一半频谱。C/C (高性能、嵌入式)FFTW“Fastest Fourier Transform in the West”是开源界的性能标杆支持多线程、SIMD但许可协议需注意。Intel MKL和ARM Performance Libraries提供了针对各自硬件高度优化的FFT实现。MATLAB (算法开发、教育)内置的fft、ifft函数简单易用配合强大的绘图和工具箱是算法开发和教学的利器。在线/实时处理对于实时音频流通常采用滑动窗口FFT或称短时傅里叶变换STFT。将长信号分帧加窗对每一帧做FFT得到随时间变化的频谱图Spectrogram。这是声谱图Spectrogram和许多实时音频效果的基础。FFT远不止是一个算法它是我们观察信号世界另一面的透镜。从理解分治思想开始到亲手实现一个蝴蝶运算再到规避工程中的种种陷阱这个过程本身就是数字信号处理入门最扎实的路径。当你下次再看到一段音频的频谱瀑布图或调试一个通信模块时希望你能想起隐藏在背后的、那个优雅而高效的快速傅里叶变换。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2629929.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…