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

从离散傅里叶变换(DFT)到快速傅里叶变换(FFT)

摘要

离散傅里叶变换(DFT)是数字信号处理领域中分析信号频域特性的重要工具,但直接计算DFT的复杂度较高,限制了其在大规模数据处理中的应用。快速傅里叶变换(FFT)的出现显著降低了计算复杂度,极大地推动了数字信号处理技术的发展。本文详细阐述了从DFT到FFT的演变过程,包括DFT的定义、计算复杂度问题,FFT的原理、算法实现以及其在实际应用中的优势,旨在帮助读者深入理解这一重要的技术变革。

在这里插入图片描述

一、引言

在数字信号处理的众多任务中,如信号滤波、频谱分析、通信系统中的调制解调等,频域分析是关键环节。离散傅里叶变换(DFT)为我们提供了将离散时间信号从时域转换到频域的方法,使得我们能够观察信号在不同频率上的分布情况。然而,DFT的直接计算涉及大量的乘法和加法运算,计算复杂度较高,尤其是当信号长度较长时,计算时间会显著增加,这在实际应用中成为了一个瓶颈。为了解决这一问题,快速傅里叶变换(FFT)应运而生。FFT通过巧妙的算法设计,大大减少了计算量,提高了计算效率,使得频域分析能够在更短的时间内完成,从而推动了数字信号处理技术在各个领域的广泛应用。

二、离散傅里叶变换(DFT)

2.1 DFT的定义

对于长度为 N N N 的离散时间序列 x [ n ] x[n] x[n] n = 0 , 1 , ⋯ , N − 1 n = 0,1,\cdots,N - 1 n=0,1,,N1,其离散傅里叶变换(DFT)定义为:
X [ k ] = ∑ n = 0 N − 1 x [ n ] e − j 2 π N k n , k = 0 , 1 , ⋯ , N − 1 X[k]=\sum_{n = 0}^{N - 1}x[n]e^{-j\frac{2\pi}{N}kn}, k = 0,1,\cdots,N - 1 X[k]=n=0N1x[n]ejN2πkn,k=0,1,,N1
其中, X [ k ] X[k] X[k] 是长度为 N N N 的离散频域序列, k k k 是离散的频率序号, e − j 2 π N e^{-j\frac{2\pi}{N}} ejN2π 通常记为 W N W_N WN,称为旋转因子。

DFT的逆变换(IDFT)定义为:
x [ n ] = 1 N ∑ k = 0 N − 1 X [ k ] e j 2 π N k n , n = 0 , 1 , ⋯ , N − 1 x[n]=\frac{1}{N}\sum_{k = 0}^{N - 1}X[k]e^{j\frac{2\pi}{N}kn}, n = 0,1,\cdots,N - 1 x[n]=N1k=0N1X[k]ejN2πkn,n=0,1,,N1

2.2 DFT的物理意义

DFT将时域的离散序列 x [ n ] x[n] x[n] 分解为 N N N 个不同频率的复指数序列的线性组合,每个复指数序列的频率为 ω k = 2 π N k \omega_k=\frac{2\pi}{N}k ωk=N2πk k = 0 , 1 , ⋯ , N − 1 k = 0,1,\cdots,N - 1 k=0,1,,N1 X [ k ] X[k] X[k] 表示序列 x [ n ] x[n] x[n] 在频率 ω k \omega_k ωk 处的频谱分量,其幅度 ∣ X [ k ] ∣ |X[k]| X[k] 反映了该频率分量的强度,相位 ∠ X [ k ] \angle X[k] X[k] 反映了该频率分量的相位信息。通过DFT,我们可以在频域中分析信号的频率成分,了解信号的特性。

2.3 DFT的计算复杂度

直接计算DFT时,对于每个 k k k 值,需要进行 N N N 次复数乘法和 N − 1 N - 1 N1 次复数加法。由于 k k k N N N 个取值,所以总的复数乘法次数约为 N 2 N^2 N2 次,复数加法次数约为 N ( N − 1 ) N(N - 1) N(N1) 次。当 N N N 较大时,计算量会急剧增加。例如,当 N = 1024 N = 1024 N=1024 时,直接计算DFT需要进行约 102 4 2 = 1048576 1024^2 = 1048576 10242=1048576 次复数乘法,这对于实时性要求较高的应用来说是难以承受的。因此,DFT计算复杂度高的问题限制了其在实际中的广泛应用。

三、快速傅里叶变换(FFT)的原理

3.1 分治思想的引入

为了降低DFT的计算复杂度,人们提出了快速傅里叶变换(FFT)算法。FFT的核心思想是利用分治策略,将一个 N N N 点的DFT分解为多个较短长度的DFT来计算。以基 - 2时间抽取FFT算法为例(假设 N = 2 M N = 2^M N=2M M M M 为正整数),把 N N N 点序列 x [ n ] x[n] x[n] n n n 的奇偶性分为两个 N / 2 N/2 N/2 点的子序列:

  • 偶数序号子序列: x 1 [ r ] = x [ 2 r ] x_1[r]=x[2r] x1[r]=x[2r] r = 0 , 1 , ⋯ , N / 2 − 1 r = 0,1,\cdots,N/2 - 1 r=0,1,,N/21
  • 奇数序号子序列: x 2 [ r ] = x [ 2 r + 1 ] x_2[r]=x[2r + 1] x2[r]=x[2r+1] r = 0 , 1 , ⋯ , N / 2 − 1 r = 0,1,\cdots,N/2 - 1 r=0,1,,N/21

N N N 点DFT X [ k ] X[k] X[k] 可以表示为:
X [ k ] = ∑ n = 0 N − 1 x [ n ] W N k n = ∑ r = 0 N / 2 − 1 x [ 2 r ] W N k ( 2 r ) + ∑ r = 0 N / 2 − 1 x [ 2 r + 1 ] W N k ( 2 r + 1 ) = ∑ r = 0 N / 2 − 1 x 1 [ r ] W N / 2 k r + W N k ∑ r = 0 N / 2 − 1 x 2 [ r ] W N / 2 k r = X 1 [ k ] + W N k X 2 [ k ] , k = 0 , 1 , ⋯ , N − 1 \begin{align*} X[k]&=\sum_{n = 0}^{N - 1}x[n]W_N^{kn}\\ &=\sum_{r = 0}^{N/2 - 1}x[2r]W_N^{k(2r)}+\sum_{r = 0}^{N/2 - 1}x[2r + 1]W_N^{k(2r+1)}\\ &=\sum_{r = 0}^{N/2 - 1}x_1[r]W_{N/2}^{kr}+W_N^k\sum_{r = 0}^{N/2 - 1}x_2[r]W_{N/2}^{kr}\\ &=X_1[k]+W_N^kX_2[k], k = 0,1,\cdots,N - 1 \end{align*} X[k]=n=0N1x[n]WNkn=r=0N/21x[2r]WNk(2r)+r=0N/21x[2r+1]WNk(2r+1)=r=0N/21x1[r]WN/2kr+WNkr=0N/21x2[r]WN/2kr=X1[k]+WNkX2[k],k=0,1,,N1
其中 W N = e − j 2 π N W_N = e^{-j\frac{2\pi}{N}} WN=ejN2π W N / 2 = e − j 2 π N / 2 = e − j 4 π N W_{N/2}=e^{-j\frac{2\pi}{N/2}}=e^{-j\frac{4\pi}{N}} WN/2=ejN/22π=ejN4π X 1 [ k ] X_1[k] X1[k] X 2 [ k ] X_2[k] X2[k] 分别是 x 1 [ r ] x_1[r] x1[r] x 2 [ r ] x_2[r] x2[r] N / 2 N/2 N/2 点DFT。

由于 X 1 [ k ] X_1[k] X1[k] X 2 [ k ] X_2[k] X2[k] 具有周期性,即 X 1 [ k + N / 2 ] = X 1 [ k ] X_1[k + N/2]=X_1[k] X1[k+N/2]=X1[k] X 2 [ k + N / 2 ] = X 2 [ k ] X_2[k + N/2]=X_2[k] X2[k+N/2]=X2[k] 所以 X [ k ] X[k] X[k] 可以进一步表示为:
{ X [ k ] = X 1 [ k ] + W N k X 2 [ k ] , k = 0 , 1 , ⋯ , N / 2 − 1 X [ k + N / 2 ] = X 1 [ k ] − W N k X 2 [ k ] , k = 0 , 1 , ⋯ , N / 2 − 1 \begin{cases} X[k]=X_1[k]+W_N^kX_2[k],& k = 0,1,\cdots,N/2 - 1\\ X[k + N/2]=X_1[k]-W_N^kX_2[k],& k = 0,1,\cdots,N/2 - 1 \end{cases} {X[k]=X1[k]+WNkX2[k],X[k+N/2]=X1[k]WNkX2[k],k=0,1,,N/21k=0,1,,N/21

这样,一个 N N N 点的DFT就可以通过两个 N / 2 N/2 N/2 点的DFT来计算。继续对 N / 2 N/2 N/2 点的DFT进行分解,直到分解为2点的DFT,最终可以将计算复杂度从 O ( N 2 ) O(N^2) O(N2) 降低到 O ( N log ⁡ 2 N ) O(N\log_2N) O(Nlog2N)

3.2 旋转因子的特性

旋转因子 W N = e − j 2 π N W_N = e^{-j\frac{2\pi}{N}} WN=ejN2π 具有以下重要特性,这些特性在FFT算法中起到了关键作用:

  • 周期性 W N k + N = W N k W_N^{k + N}=W_N^k WNk+N=WNk,这是因为 e − j 2 π N ( k + N ) = e − j 2 π N k e − j 2 π = e − j 2 π N k e^{-j\frac{2\pi}{N}(k + N)}=e^{-j\frac{2\pi}{N}k}e^{-j2\pi}=e^{-j\frac{2\pi}{N}k} ejN2π(k+N)=ejN2πkej2π=ejN2πk利用周期性,我们可以避免重复计算旋转因子的值。
  • 对称性 W N k + N / 2 = − W N k W_N^{k+N/2}=-W_N^k WNk+N/2=WNk,因为 W N k + N / 2 = e − j 2 π N ( k + N / 2 ) = e − j 2 π N k e − j π = − e − j 2 π N k = − W N k W_N^{k + N/2}=e^{-j\frac{2\pi}{N}(k + N/2)}=e^{-j\frac{2\pi}{N}k}e^{-j\pi}=-e^{-j\frac{2\pi}{N}k}=-W_N^k WNk+N/2=ejN2π(k+N/2)=ejN2πke=ejN2πk=WNk对称性可以减少旋转因子的计算量,进一步提高算法效率。

3.3 蝶形运算

蝶形运算是FFT算法中的基本运算单元。对于基 - 2 FFT算法,一个蝶形运算涉及两个输入数据 a a a b b b,以及一个旋转因子 W N k W_N^k WNk,其输出为:
{ A = a + W N k b B = a − W N k b \begin{cases} A=a + W_N^kb\\ B=a - W_N^kb \end{cases} {A=a+WNkbB=aWNkb

在基 - 2时间抽取FFT算法中,每一级都由多个蝶形运算组成。通过不断地进行蝶形运算,最终可以得到 N N N 点的FFT结果。蝶形运算的优点是只需要一次复数乘法和两次复数加法,大大减少了计算量。

四、FFT算法的实现

4.1 基 - 2 时间抽取 FFT 算法的实现步骤

4.1.1 输入序列的重排

在基 - 2 时间抽取 FFT 算法中,输入序列 x [ n ] x[n] x[n] 需要按照比特倒序的方式进行重排。假设序列长度 N = 2 M N = 2^M N=2M,对于序号 n n n,将其表示为 M M M 位二进制数,然后将这 M M M 位二进制数按位反转得到新的序号 n ′ n' n,将 x [ n ] x[n] x[n] 放置到 x [ n ′ ] x[n'] x[n] 的位置。例如,当 N = 8 N = 8 N=8 M = 3 M = 3 M=3)时, n = 3 n = 3 n=3 的二进制表示为 011 011 011,比特倒序后为 110 110 110,即 6 6 6,那么 x [ 3 ] x[3] x[3] 要与 x [ 6 ] x[6] x[6] 交换位置。这样做的目的是为后续的蝶形运算提供方便,使得运算可以按照规则的顺序进行。

4.1.2 多级蝶形运算

将重排后的序列进行 M M M 级蝶形运算,每一级包含 N / 2 N/2 N/2 个蝶形单元。以第 m m m 级( m = 1 , 2 , ⋯ , M m = 1,2,\cdots,M m=1,2,,M)为例,同一级中每个蝶形单元的旋转因子为 W N r 2 M − m W_N^{r2^{M - m}} WNr2Mm其中 r = 0 , 1 , ⋯ , 2 m − 1 − 1 r = 0,1,\cdots,2^{m - 1}-1 r=0,1,,2m11。每一级的蝶形运算都根据前面提到的蝶形运算公式 A = a + W N k b A=a + W_N^kb A=a+WNkb B = a − W N k b B=a - W_N^kb B=aWNkb 进行计算,不断更新序列的值。

下面是一个用 Python 实现基 - 2 时间抽取 FFT 算法的示例代码:

import numpy as npdef bit_reverse(x):N = len(x)M = int(np.log2(N))x_reversed = np.zeros(N, dtype=complex)for n in range(N):binary_n = bin(n)[2:].zfill(M)reversed_n = int(binary_n[::-1], 2)x_reversed[n] = x[reversed_n]return x_reverseddef fft(x):N = len(x)if N <= 1:return xx = bit_reverse(x)M = int(np.log2(N))for m in range(1, M + 1):group_size = 2**mhalf_group_size = group_size // 2for k in range(0, N, group_size):for r in range(half_group_size):W = np.exp(-2j * np.pi * r / group_size)a = x[k + r]b = x[k + r + half_group_size]x[k + r] = a + W * bx[k + r + half_group_size] = a - W * breturn x

4.2 其他 FFT 算法变体

除了基 - 2 时间抽取 FFT 算法,还有基 - 2 频率抽取 FFT 算法、基 - 4 FFT 算法以及分裂基 FFT 算法等。

4.2.1 基 - 2 频率抽取 FFT 算法

基 - 2 频率抽取 FFT 算法与基 - 2 时间抽取 FFT 算法类似,但它是在频域进行分解。它将 N N N 点 DFT 分解为两个 N / 2 N/2 N/2 点 DFT 的组合,不过分解的方式和蝶形运算的结构与时间抽取算法有所不同。频率抽取算法在输入序列不需要进行比特倒序重排,而是在输出序列进行比特倒序,这在某些应用场景中可能更具优势。

4.2.2 基 - 4 FFT 算法

当序列长度 N N N 是 4 的幂次方(即 N = 4 M N = 4^M N=4M)时,可以使用基 - 4 FFT 算法。基 - 4 算法将 N N N 点 DFT 分解为四个 N / 4 N/4 N/4 点 DFT,相比于基 - 2 算法,它能进一步减少乘法运算的次数。因为基 - 4 蝶形运算可以用更少的乘法实现,从而提高计算效率。

4.2.3 分裂基 FFT 算法

分裂基 FFT 算法结合了基 - 2 和基 - 4 算法的优点,它在分解过程中根据序列长度灵活地采用基 - 2 和基 - 4 的分解方式。分裂基算法在计算效率上通常优于单纯的基 - 2 或基 - 4 算法,尤其是对于较长的序列,能显著减少乘法和加法的运算次数。

五、FFT 相对于 DFT 的优势

5.1 计算复杂度的显著降低

如前文所述,直接计算 DFT 的复杂度为 O ( N 2 ) O(N^2) O(N2),而 FFT 算法(如基 - 2 时间抽取 FFT)的复杂度为 O ( N log ⁡ 2 N ) O(N\log_2N) O(Nlog2N)。当 N N N 较大时, N log ⁡ 2 N N\log_2N Nlog2N 远小于 N 2 N^2 N2。例如,当 N = 1024 N = 1024 N=1024 时,DFT 需要约 102 4 2 = 1048576 1024^2 = 1048576 10242=1048576 次复数乘法,而基 - 2 FFT 只需要约 1024 2 log ⁡ 2 1024 = 512 × 10 = 5120 \frac{1024}{2}\log_2{1024}= 512\times10 = 5120 21024log21024=512×10=5120 次复数乘法,计算效率得到了极大的提高。这使得 FFT 能够处理更长的信号序列,并且在更短的时间内完成频域分析任务。

5.2 实时处理能力的提升

在许多实际应用中,如音频和视频处理、雷达信号处理等,对信号处理的实时性要求很高。由于 FFT 算法大大减少了计算量,使得系统能够在更短的时间内完成频域分析,从而满足实时处理的需求。例如,在音频实时特效处理中,通过 FFT 可以快速分析音频信号的频谱,然后根据频谱信息进行滤波、均衡等处理,最后通过逆 FFT 将处理后的频谱转换回时域,实现实时的音频效果调整。

5.3 硬件实现的可行性增强

较低的计算复杂度使得 FFT 更容易在硬件上实现。相比于 DFT 所需的大量乘法器和加法器,FFT 算法的规则结构和较少的运算次数使得它可以用更简单的硬件电路来实现。例如,在现场可编程门阵列(FPGA)和专用集成电路(ASIC)中,FFT 模块可以高效地实现,从而为各种嵌入式系统和实时信号处理设备提供强大的频域处理能力。

六、FFT 在实际应用中的广泛应用

6.1 音频处理

在音频处理领域,FFT 被广泛应用于音频的频谱分析、滤波、压缩等方面。通过 FFT 可以将音频信号从时域转换到频域,分析音频信号的频率成分,例如检测音频中的高音、低音成分,以及识别音频中的特定频率特征,如人声的基频和各次谐波。在音频滤波中,可以根据频谱分析的结果设计滤波器,去除不需要的频率成分,如噪声。在音频压缩方面,FFT 可以帮助确定音频信号的主要频率分量,然后对这些分量进行量化和编码,从而实现音频数据的压缩。

6.2 图像处理

在图像处理中,FFT 用于图像的频域滤波、特征提取等操作。图像的低频成分对应着图像的整体轮廓和缓慢变化的部分,高频成分对应着图像的细节和边缘信息。通过对图像进行二维 FFT 变换,可以将图像从空间域转换到频域,然后在频域中对图像进行滤波处理。例如,使用低通滤波器可以平滑图像,去除图像中的高频噪声;使用高通滤波器可以增强图像的边缘信息,使图像更加清晰。此外,FFT 还可以用于图像的特征提取,通过分析图像的频谱特征来识别图像中的物体或模式。

6.3 通信系统

在通信系统中,FFT 是正交频分复用(OFDM)技术的核心算法。OFDM 是一种高效的多载波调制技术,它将高速数据流分成多个低速子数据流,每个子数据流在不同的子载波上进行传输。FFT 和逆 FFT 用于实现 OFDM 信号在频域和时域之间的转换。在发射端,通过逆 FFT 将频域的子载波数据转换为时域的 OFDM 符号;在接收端,通过 FFT 将接收到的时域 OFDM 符号转换回频域,然后进行解调。FFT 的高效计算使得 OFDM 技术能够在有限的频谱资源下实现高速、可靠的通信。

6.4 雷达信号处理

在雷达信号处理中,FFT 用于对雷达回波信号进行频谱分析,以确定目标的速度、距离等信息。雷达发射的信号遇到目标后会产生回波,回波信号包含了目标的各种信息。通过对回波信号进行 FFT 变换,可以得到其频谱特性,根据多普勒频移原理计算目标的速度;根据回波信号的延迟时间和频率信息,可以估计目标的距离。FFT 的快速计算能力使得雷达系统能够实时地对目标进行检测和跟踪。

七、结论

从离散傅里叶变换(DFT)到快速傅里叶变换(FFT)的发展是数字信号处理领域的一个重要里程碑。DFT 为我们提供了一种将离散时间信号从时域转换到频域的基本方法,但由于其计算复杂度高,限制了其在大规模数据处理和实时应用中的使用。FFT 算法通过引入分治思想,利用旋转因子的特性和蝶形运算,成功地将计算复杂度从 O ( N 2 ) O(N^2) O(N2) 降低到 O ( N log ⁡ 2 N ) O(N\log_2N) O(Nlog2N),大大提高了计算效率。

FFT 不仅在计算复杂度上具有显著优势,还提升了信号处理的实时性和硬件实现的可行性。它在音频处理、图像处理、通信系统、雷达信号处理等众多实际应用领域发挥着至关重要的作用,推动了这些领域的技术发展。随着科技的不断进步,FFT 算法也在不断改进和优化,出现了多种变体算法,以适应不同的应用场景和需求。

相关文章:

从离散傅里叶变换(DFT)到快速傅里叶变换(FFT)

摘要 离散傅里叶变换&#xff08;DFT&#xff09;是数字信号处理领域中分析信号频域特性的重要工具&#xff0c;但直接计算DFT的复杂度较高&#xff0c;限制了其在大规模数据处理中的应用。快速傅里叶变换&#xff08;FFT&#xff09;的出现显著降低了计算复杂度&#xff0c;极…...

【STM32】HAL库USB虚拟U盘MSC配置及采用自带的Flash作为文件系统

【STM32】HAL库USB虚拟U盘MSC实现配置及采用自带的Flash作为文件系统 本文将自带的Flash作为文件系统 通过配置USB的MSC功能实现虚拟U盘 没有单独建立FATFS文件系统 仅仅是配置USB和Flash读写而已 当然 这里也可以用外部Flash等等 也可以配置文件系统来进行套壳 但总体而言不如…...

Math Reference Notes: 符号函数

1. 符号函数的定义 符号函数&#xff08;Sign Function&#xff09; sgn ( x ) \text{sgn}(x) sgn(x) 是一个将实数 ( x ) 映射为其 符号值&#xff08;即正数、负数或零&#xff09;的函数。 它的定义如下&#xff1a; sgn ( x ) { 1 如果 x > 0 0 如果 x 0 − 1 如…...

拉格朗日乘数法算法详解Python实现

目录 一、拉格朗日乘数法算法详解1.1 基本思想1.2 数学推导1.3 算法步骤1.4 算法在编程中的实现 二、案例分析案例一&#xff1a;二维最优化问题——求 f ( x , y ) x 2 y 2 f(x,y)x^2y^2 f(x,y)x2y2 在约束 x y 1 xy1 xy1 下的极值2.1.1 问题描述2.1.2 数学模型构建2.1.…...

ip属地是手机号还是手机位置?一文理清

在数字化和网络化的今天&#xff0c;IP属地这一概念逐渐成为了人们关注的焦点。特别是在社交媒体和在线平台上&#xff0c;IP属地的显示往往让人联想到用户的地理位置。然而&#xff0c;关于IP属地到底与手机号还是手机位置有关&#xff0c;却存在着不少误解和混淆。本文将深入…...

C++常用拷贝和替换算法

算法简介&#xff1a; copy // 容器内指定的元素拷贝到另一容器replace // 将容器内指定范围的旧元素改为新元素replace_if // 容器内指定范围满足条件的元素替换为新元素swap //互换两个容器的元素 1. copy 功能描述&#xff1a; 将容器内指定范围的数据拷贝到另一容器中函…...

vue项目搭建

1.准备工作&#xff0c;按照下面的安装一下脚手架vue-cli node16安装vue-cli时报错&#xff1a;需要node&#xff1e;20&#xff08;但根本就不是版本问题&#xff09;-CSDN博客文章浏览阅读157次&#xff0c;点赞4次&#xff0c;收藏2次。这种情况我碰到不下5次了&#xff0c…...

Java进阶面试八股文

1、Java SE和Java EE区别&#xff1f; Java SE 是 Java 的基础版本&#xff0c;Java EE 是 Java 的高级版本。Java SE 更适合开发桌面应用程序或简单的服务器应用程序&#xff0c;Java EE 更适合开发复杂的企业级应用程序或 Web 应用程序。 2、JVM和JRE和JDK区别&#xff1f;…...

Python Django 嵌入 Grafana Dashboard(随手记)

作为一名网络工程师/运维工程师&#xff0c;现在都在往DevOps的方向发展。其中大家都不可避免的会往自己开发平台的方向发展。 那么如何将自己制作的 Grafana 面板 引入到自己的平台上&#xff1f; 一般来说&#xff0c;大家都会选择Python来作为自己开发的语言&#xff0c;并会…...

[Android] IKTV专享版

[Android] IKTV专享版 链接&#xff1a;https://pan.xunlei.com/s/VOILXXuEd3ASo93c88UW79sxA1?pwd4tsw# 2025年2月最新免费K歌神器&#xff01;家庭KTV软件&#xff0c;手机平板电视盒子电脑都可用...

阿里 Java 岗个人面经分享(技术三面 + 技术 HR 面):Java 基础 +Spring+JVM+ 并发编程 + 算法 + 缓存

技术一面 20 分钟 1、自我介绍 说了很多遍了&#xff0c;很流畅捡重点介绍完。 2、问我数据结构算法好不好 挺好的&#xff08;其实心还是有点虚&#xff0c;不过最近刷了很多题也只能壮着胆子充胖子了&#xff09; 3、找到单链表的三等分点&#xff0c;如果单链表是有环的…...

C++多线程编程——call_once和单例模式

目录 1. 前言 2. call_once和once_flag 3. 后记 3.1 单例类的析构问题 3.2 饿汉式单例模式的线程安全问题 1. 前言 之前在讲解单例模式时&#xff0c;有提到懒汉式单例模式使用了双重检测Double-Checked Locking Pattern (DCLP)来解决多线程的安全访问问题。但是该方法也…...

vue2-为啥data属性是一个函数而不是对象

vue2-为啥data属性是一个函数而不是对象 1. data在vue实例和组件中的表现差异 vue实例的时候&#xff0c;data既可以是一个对象也可以是一个函数 new Vue({data:{//对象name:tom},data(){//函数return{name:tom}} })而在组件中定义data&#xff0c;只能是函数&#xff0c;如…...

Spark--算子执行原理

一、sortByKey SortByKey是一个transformation算子&#xff0c;但是会触发action&#xff0c;因为在sortByKey方法内部&#xff0c;会对每个分区进行采样&#xff0c;构建分区规则&#xff08;RangePartitioner&#xff09;。 内部执行流程 1、创建RangePartitioner part&…...

keil 单步调试

一、常见错误分析 warningerror警告错误 不影响编译过程 能够输出Hex文件 无法完成编译 不输出Hex文件 注意的是,warning的信息是要去关注的。 下面的UNCALLED SEGMENT除外 二、单步调试配置 1、在keil中添加单片机型号 本文不详细介绍,如有需要可查看这篇文章:...

html的字符实体和颜色表示

在HTML中&#xff0c;颜色可以通过以下几种方式表示&#xff0c;以下是具体的示例&#xff1a; 1. 十六进制颜色代码 十六进制颜色代码以#开头&#xff0c;后面跟随6个字符&#xff0c;每两个字符分别表示红色、绿色和蓝色的强度。例如&#xff1a; • #FF0000&#xff1a;纯红…...

[数据结构] 线性表和顺序表

目录 线性表 顺序表的实现 顺序表各个方法的实现 boolean isFull() -- 判断数组是否放满 : void add(int data) -- 在数组末尾插入新元素 : void add(int pos,int data) -- 在指定位置插入元素 : boolean contain(int toFind) -- 判断是否包含某个元素 int indexOf(in…...

第12章:基于TransUnet和SwinUnet网络实现的医学图像语义分割:腹部13器官分割(网页推理)

目录 1. 前言 2. TransUnet 和 SwinUnet 3. 腹部多器官分割 4. 训练 5. 推理 6. 项目下载 1. 前言 TransUNet 是一种用于医学图像分割的混合架构&#xff0c;结合了 Transformer 和 U-Net 的优势。它利用 Transformer 的全局上下文建模能力和 U-Net 的精确定位特性&…...

DS图(下)(19)

文章目录 前言一、最短路径的概念二、单源最短路径-Dijkstra算法三、单源最短路径-Bellman-Ford算法四、多源最短路径-Floyd-Warshall算法总结 前言 加油&#xff0c;今天就是图的最后一篇了&#xff0c;撑住&#xff01;&#xff01;   今天我们要学的就是最短路径问题&…...

鸿蒙Harmony-Progress组件概述

鸿蒙Harmony-Progress组件概述 1.1Progress组件概述 作用&#xff1a;显示操作或任务的进度&#xff0c;支持线性&#xff0c;环形&#xff0c;刻度等多种样式适用场景&#xff1a;文件上传/下载、任务完成度、系统状态反馈等 2.1基础属性&#xff08;参考官方文档&#xff…...

流数据库中的RisingWave和Materialize

流数据库&#xff08;Streaming Database&#xff09;是一种专门设计用于处理大量实时流数据的数据库&#xff0c;它能够在数据生成时立即进行处理&#xff0c;从而实现实时洞察和分析。RisingWave和Materialize都是这一领域的代表性技术。RisingWave和Materialize都是强大的流…...

【C++】多态详细讲解

本篇来聊聊C面向对象的第三大特性-多态。 1.多态的概念 多态通俗来说就是多种形态。多态分为编译时多态(静态多态)和运⾏时多态(动态多态)。 编译时多态&#xff1a;主要就是我们前⾯讲的函数重载和函数模板&#xff0c;他们传不同类型的参数就可以调⽤不同的函数&#xff0c;通…...

防火墙的安全策略

1.VLAN 2属于办公区;VLAN 3属于生产区&#xff0c;创建时间段 [FW]ip address-set BG type object [FW-object-address-set-BG]address 192.168.1.0 mask 25 [FW]ip address-set SC type object [FW-object-address-set-SC]address 192.168.1.129 mask 25 [FW]ip address-se…...

Android 进程间通信

什么是IPC&#xff1f; Android 进程间通信&#xff08;IPC&#xff0c;Inter-Process Communication&#xff09;是Android操作系统中不同进程间交换数据和资源的一种机制。由于Android是多任务操作系统&#xff0c;每个应用通常运行在自己的进程中&#xff0c;以提高安全性和…...

【优先算法】专题——位运算

在讲解位运算之前我们来总结一下常见的位运算 一、常见的位运算 1.基础为运算 << &&#xff1a;有0就是0 >> |&#xff1a;有1就是1 ~ ^&#xff1a;相同为0&#xff0c;相异位1 /无进位相加 2.给一个数 n&#xff0c;确定它的二进制表示…...

深入理解k8s中的容器存储接口(CSI)

CSI出现的原因 K8s原生支持一些存储类型的PV&#xff0c;像iSCSI、NFS等。但这种方式让K8s代码与三方存储厂商代码紧密相连&#xff0c;带来不少麻烦。比如更改存储代码就得更新K8s组件&#xff0c;成本高&#xff1b;存储代码的bug还会影响K8s稳定性&#xff1b;K8s社区维护和…...

ZZNUOJ(C/C++)基础练习1061——1070(详解版)

目录 1061 : 顺序输出各位数字 C语言版 C版 1062 : 最大公约数 C C 1063 : 最大公约与最小公倍 C C 1064 : 加密字符 C C 1065 : 统计数字字符的个数 C C 1066 : 字符分类统计 C C 1067 : 有问题的里程表 C C 1068 : 进制转换 C C C&#xff08;容器stack…...

ES6 变量解构赋值总结

1. 数组的解构赋值 1.1 基本用法 // 基本数组解构 const [a, b, c] [1, 2, 3]; console.log(a); // 1 console.log(b); // 2 console.log(c); // 3// 跳过某些值 const [x, , y] [1, 2, 3]; console.log(x); // 1 console.log(y); // 3// 解构剩余元素 const [first, ...re…...

机理模型与数据模型融合的方式

机理模型与数据模型的融合旨在结合两者的优势&#xff0c;以提供更准确、可靠的预测和决策支持。以下是几种常见的融合方式及其示例&#xff1a; 1. 特征增强&#xff08;Feature Augmentation&#xff09; 描述&#xff1a;将由机理模型计算得到的结果作为额外特征加入到数据…...

高效 MyBatis SQL 写法一

高效 MyBatis SQL 写法一 前言 MyBatis 作为一款优秀的持久层框架&#xff0c;极大地简化了数据库操作。 然而&#xff0c;在实际开发中&#xff0c;XML 配置的编写仍然可能显得繁琐。 本文将分享一些 MyBatis 动态 SQL 的优质写法&#xff0c;帮助开发者提升效率并减少错误…...

vue3中的ref相关的api及用法

在 Vue 3 中&#xff0c;ref 相关的 API 主要用于管理响应式数据。以下是 ref 相关的 API 及其用法&#xff1a; 1. ref ref 用于创建响应式的基本数据类型或对象。 用法示例&#xff1a; <script setup> import { ref } from vue;const count ref(0);const incremen…...

3 卷积神经网络CNN

1 Image Classification (Neuron Version) – 1.1 Observation 1 1.2 Observation 2 如果不同的receptive field需要相同功能的neuron&#xff0c;可以使这些neuron共享参数 1.3 Benefit of Convolutional Layer 2 Image Classification (Filter Version) 不用担心filter大小…...

CSV数据分析智能工具(基于OpenAI API和streamlit)

utils.py&#xff1a; from langchain_openai import ChatOpenAI from langchain_experimental.agents.agent_toolkits import create_csv_agent import jsonPROMPT_TEMPLATE """你是一位数据分析助手&#xff0c;你的回应内容取决于用户的请求内容。1. 对于文…...

解决php8.3无法加载curl扩展

把它的值更改为扩展存在的目录的绝对路径(扩展存在的目录为有php_xxx.dll存在的目录) extension_dir "e:\serv\php83\ext" 然后从php根目录复制 libssh2.dll 和 libcrypto-*.dll 和 libssl-*.dll 到Apache根目录下的bin目录 重启apache服务即可...

拍照对比,X70 PRO与X90 PRO+的细节差异

以下是局部截图&#xff08;上X70P下X90PP&#xff09; 对比1 这里看不出差异。 对比2 X90PP的字明显更清楚。 对比3 中下的字&#xff0c;X90PP显然更清楚。...

《MPRnet》学习笔记

paper&#xff1a;2102.02808 GitHub&#xff1a;swz30/MPRNet: [CVPR 2021] Multi-Stage Progressive Image Restoration. SOTA results for Image deblurring, deraining, and denoising. 目录 摘要 1、介绍 2、相关工作 2.1 单阶段方法 2.2 多阶段方法 2.3 注意力机…...

机器学习-线性回归(参数估计之结构风险最小化)

前面我们已经了解过关于机器学习中的结构风险最小化准则&#xff0c;包括L1 正则化&#xff08;Lasso&#xff09;、L2 正则化&#xff08;Ridge&#xff09;、Elastic Net&#xff0c;现在我们结合线性回归的场景&#xff0c;来了解一下线性回归的结构风险最小化&#xff0c;通…...

C++11详解(二) -- 引用折叠和完美转发

文章目录 2. 右值引用和移动语义2.6 类型分类&#xff08;实践中没什么用&#xff09;2.7 引用折叠2.8 完美转发2.9 引用折叠和完美转发的实例 2. 右值引用和移动语义 2.6 类型分类&#xff08;实践中没什么用&#xff09; C11以后&#xff0c;进一步对类型进行了划分&#x…...

深度学习系列--01.入门

一.深度学习概念 深度学习&#xff08;Deep Learning&#xff09;是机器学习的分支&#xff0c;是指使用多层的神经网络进行机器学习的一种手法抖音百科。它学习样本数据的内在规律和表示层次&#xff0c;最终目标是让机器能够像人一样具有分析学习能力&#xff0c;能够识别文字…...

熵采样在分类任务中的应用

熵采样在分类任务中的应用 在机器学习的分类任务里,数据的标注成本常常制约着模型性能的提升。主动学习中的熵采样策略,为解决这一难题提供了新的思路。本文将带你深入了解熵采样在分类任务中的原理、应用及优势。 一、熵采样的原理(优化版) 熵,源于信息论,是对不确定…...

vite配置之---依赖优化选项

vite optimizeDeps 配置项主要在 开发环境 中对依赖项发挥作用 optimizeDeps.entries vite optimizeDeps.entries 是 Vite 配置中的一个选项&#xff0c;用来指定要优化的入口文件。这在开发环境中尤其有用&#xff0c;因为它告诉 Vite 需要预构建哪些文件&#xff0c;以便加速…...

Shell基础:中括号的使用

在Shell脚本中&#xff0c;中括号&#xff08;[ ... ] 和 [[ ... ]]&#xff09;是一种常见的条件测试结构。它们用于进行文件类型检查、值比较以及逻辑判断。通过了解它们的不同特点和用法&#xff0c;能够帮助你编写更加高效、安全且易读的脚本。本文将详细介绍Shell中单中括…...

oracle ORA-27054报错处理

现象 在oracle执行expdp&#xff0c;rman备份&#xff0c;xtts的时候,由于没有足够的本地空间&#xff0c;只能使用到NFS的文件系统但有时候会出现如下报错 ORA-27054: NFS file system where the file is created or resides is not mounted with correct options根据提示信…...

SpringCloud速通教程

视频地址 文档地址 3. SpringCloud - 快速通关...

MapReduce分区

目录 1. MapReduce分区1.1 哈希分区1.2 自定义分区 2. 成绩分组2.1 Map2.2 Partition2.3 Reduce 3. 代码和结果3.1 pom.xml中依赖配置3.2 工具类util3.3 GroupScores3.4 结果 参考 本文引用的Apache Hadoop源代码基于Apache许可证 2.0&#xff0c;详情请参阅 Apache许可证2.0。…...

python算法和数据结构刷题[3]:哈希表、滑动窗口、双指针、回溯算法、贪心算法

回溯算法 「所有可能的结果」&#xff0c;而不是「结果的个数」&#xff0c;一般情况下&#xff0c;我们就知道需要暴力搜索所有的可行解了&#xff0c;可以用「回溯法」。 回溯算法关键在于:不合适就退回上一步。在回溯算法中&#xff0c;递归用于深入到所有可能的分支&…...

JDK 中 NIO 框架设计与实现:深入剖析及实战样例

一、引言 在 Java 的发展历程中&#xff0c;I/O&#xff08;Input/Output&#xff09;操作一直是构建高效、稳定应用程序的关键环节。传统的 Java I/O 操作基于流&#xff08;Stream&#xff09;的方式&#xff0c;虽然简单易用&#xff0c;但在面对高并发、大规模数据传输等场…...

基于springboot校园点歌系统

基于Spring Boot的校园点歌系统是一种专为校园场景设计的音乐点播平台&#xff0c;它能够丰富学生的校园生活&#xff0c;提升学生的娱乐体验。以下是对该系统的详细介绍&#xff1a; 一、系统背景与意义 在校园环境中&#xff0c;学生们对于音乐有着浓厚的兴趣&#xff0c;传…...

Spring 核心技术解析【纯干货版】- IX:Spring 数据访问模块 Spring-Jdbc 模块精讲

在现代企业级应用中&#xff0c;数据访问层的稳定性和高效性至关重要。为了简化和优化数据库操作&#xff0c;Spring Framework 提供了 Spring-JDBC 模块&#xff0c;旨在通过高度封装的 JDBC 操作&#xff0c;简化开发者的编码负担&#xff0c;减少冗余代码&#xff0c;同时提…...

React开发中箭头函数返回值陷阱的深度解析

React开发中箭头函数返回值陷阱的深度解析 一、箭头函数的隐式返回机制&#xff1a;简洁背后的规则二、块函数体中的显式返回要求&#xff1a;容易被忽视的细节三、真实场景下的案例分析案例1&#xff1a;忘记return导致组件渲染失败案例2&#xff1a;异步操作中的返回值陷阱 四…...