加了点东西
147
Collection/KMP算法.md
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
---
|
||||||
|
tags:
|
||||||
|
- KMP
|
||||||
|
- AI生成
|
||||||
|
- C语言
|
||||||
|
---
|
||||||
|
KMP(Knuth-Morris-Pratt)算法是一种用于字符串匹配的算法,它能在O(n+m)的时间复杂度内完成字符串的匹配,其中n是主串的长度,m是模式串的长度。这个算法是由Donald Knuth、Vaughan Pratt和Vaughan Morris在1970年共同发明的。
|
||||||
|
|
||||||
|
KMP算法的主要思想是利用已经匹配过的信息,避免再次从头开始匹配。具体来说,KMP算法在匹配失败后,能够知道模式串中有一部分字符是与主串匹配的,因此不需要重新匹配这些字符。
|
||||||
|
|
||||||
|
KMP算法的关键在于构造一个“部分匹配表”(也称为“失败函数”或“跳转表”),这个表记录了模式串中每个位置的最长公共前后缀的长度。在匹配过程中,如果发生了匹配失败,就可以根据这个表来确定下一步应该比较的位置,从而避免了不必要的比较。
|
||||||
|
|
||||||
|
KMP算法的具体实现过程如下:
|
||||||
|
|
||||||
|
1. 构造部分匹配表。对于模式串中的每个位置i(1≤i≤m),计算以该位置结尾的最长公共前后缀的长度,并将结果存储在部分匹配表的第i个位置。这个计算过程可以通过动态规划来实现。
|
||||||
|
|
||||||
|
2. 进行字符串匹配。从主串的第一个字符和模式串的第一个字符开始比较,如果相等,则继续比较下一个字符;如果不相等,则根据部分匹配表来确定下一步应该比较的位置。重复这个过程,直到匹配成功或者遍历完整个主串。
|
||||||
|
|
||||||
|
KMP算法的时间复杂度为O(n+m),其中n是主串的长度,m是模式串的长度。这个算法在实际应用中非常广泛,特别是在需要频繁进行字符串匹配的场景中,如搜索引擎、文本编辑器等。
|
||||||
|
|
||||||
|
下面是一个用C语言实现的KMP(Knuth-Morris-Pratt)字符串匹配算法的示例代码。这个示例中,我们实现了KMP算法来在一个主字符串(text)中查找一个模式字符串(pattern)的所有出现位置。
|
||||||
|
|
||||||
|
```c
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// 函数原型声明
|
||||||
|
|
||||||
|
void computeLPSArray(char *pat, int M, int *lps);
|
||||||
|
|
||||||
|
void KMPSearch(char *pat, char *txt);
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
char text[] = "ABABDABACDABABCABAB";
|
||||||
|
|
||||||
|
char pattern[] = "ABABCABAB";
|
||||||
|
|
||||||
|
printf("Text: %s\n", text);
|
||||||
|
|
||||||
|
printf("Pattern: %s\n", pattern);
|
||||||
|
|
||||||
|
KMPSearch(pattern, text);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算LPS(最长公共前后缀)数组
|
||||||
|
|
||||||
|
void computeLPSArray(char *pat, int M, int *lps) {
|
||||||
|
|
||||||
|
int len = 0; // 最长公共前后缀的长度
|
||||||
|
|
||||||
|
lps[0] = 0; // lps[0] 总是0
|
||||||
|
|
||||||
|
int i = 1;
|
||||||
|
|
||||||
|
while (i < M) {
|
||||||
|
|
||||||
|
if (pat[i] == pat[len]) {
|
||||||
|
|
||||||
|
len++;
|
||||||
|
|
||||||
|
lps[i] = len;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (len != 0) {
|
||||||
|
|
||||||
|
len = lps[len - 1];
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
lps[i] = 0;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// KMP字符串匹配算法
|
||||||
|
|
||||||
|
void KMPSearch(char *pat, char *txt) {
|
||||||
|
|
||||||
|
int M = strlen(pat);
|
||||||
|
|
||||||
|
int N = strlen(txt);
|
||||||
|
|
||||||
|
int lps[M];
|
||||||
|
|
||||||
|
int j = 0; // 模式串的索引
|
||||||
|
|
||||||
|
// 计算LPS数组
|
||||||
|
|
||||||
|
computeLPSArray(pat, M, lps);
|
||||||
|
|
||||||
|
int i = 0; // 文本串的索引
|
||||||
|
|
||||||
|
while (i < N) {
|
||||||
|
|
||||||
|
if (pat[j] == txt[i]) {
|
||||||
|
|
||||||
|
j++;
|
||||||
|
|
||||||
|
i++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j == M) {
|
||||||
|
|
||||||
|
printf("Pattern found at index %d \n", i - j);
|
||||||
|
|
||||||
|
j = lps[j - 1];
|
||||||
|
|
||||||
|
} else if (i < N && pat[j] != txt[i]) {
|
||||||
|
|
||||||
|
if (j != 0)
|
||||||
|
|
||||||
|
j = lps[j - 1];
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
i = i + 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
在这个示例中,`computeLPSArray`函数计算了模式串的最长公共前后缀数组(LPS数组),而`KMPSearch`函数使用这个数组来在文本串中查找模式串。当找到匹配时,它会打印出模式串在主字符串中的起始索引。
|
||||||
|
|
||||||
|
你可以编译并运行这段代码来测试KMP算法。请确保你的编译器支持C语言标准,并且已经正确设置了编译环境。
|
||||||
|
|
||||||
|
内容由AI大模型生成,仅供参考
|
||||||
93
Collection/PID控制算法.md
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
---
|
||||||
|
tags:
|
||||||
|
- PID
|
||||||
|
- AI生成
|
||||||
|
- C语言
|
||||||
|
---
|
||||||
|
以下是一个简单的C语言实现PID控制算法的程序示例:
|
||||||
|
|
||||||
|
```c
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
// PID控制器结构体
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
double kp; // 比例系数
|
||||||
|
|
||||||
|
double ki; // 积分系数
|
||||||
|
|
||||||
|
double kd; // 微分系数
|
||||||
|
|
||||||
|
double previous_error; // 上一次的误差
|
||||||
|
|
||||||
|
double integral; // 误差积分
|
||||||
|
|
||||||
|
} PIDController;
|
||||||
|
|
||||||
|
// PID计算函数
|
||||||
|
|
||||||
|
double PID_Compute(PIDController* pid, double setpoint, double actual_value, double dt) {
|
||||||
|
|
||||||
|
double error = setpoint - actual_value;
|
||||||
|
|
||||||
|
pid->integral += error * dt;
|
||||||
|
|
||||||
|
double derivative = (error - pid->previous_error) / dt;
|
||||||
|
|
||||||
|
double output = pid->kp * error + pid->ki * pid->integral + pid->kd * derivative;
|
||||||
|
|
||||||
|
pid->previous_error = error;
|
||||||
|
|
||||||
|
return output;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
// 初始化PID控制器
|
||||||
|
|
||||||
|
PIDController pid;
|
||||||
|
|
||||||
|
pid.kp = 1.0;
|
||||||
|
|
||||||
|
pid.ki = 0.1;
|
||||||
|
|
||||||
|
pid.kd = 0.01;
|
||||||
|
|
||||||
|
pid.previous_error = 0.0;
|
||||||
|
|
||||||
|
pid.integral = 0.0;
|
||||||
|
|
||||||
|
// 模拟控制过程
|
||||||
|
|
||||||
|
double setpoint = 100.0; // 设定目标值
|
||||||
|
|
||||||
|
double actual_value = 0.0; // 实际值
|
||||||
|
|
||||||
|
double dt = 0.1; // 时间间隔
|
||||||
|
|
||||||
|
double output; // PID输出
|
||||||
|
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
|
||||||
|
output = PID_Compute(&pid, setpoint, actual_value, dt);
|
||||||
|
|
||||||
|
actual_value += output; // 假设输出直接控制实际值
|
||||||
|
|
||||||
|
printf("Time: %d, Actual Value: %f, Error: %f, Output: %f\n", i, actual_value, setpoint - actual_value, output);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
这个示例程序定义了一个`PIDController`结构体,包含了PID控制器的参数(比例系数`kp`、积分系数`ki`、微分系数`kd`)以及状态变量(上一次的误差`previous_error`和误差积分`integral`)。`PID_Compute`函数根据设定目标值、实际值和时间间隔计算PID输出。在`main`函数中,我们初始化了一个PID控制器,并模拟了一个控制过程,其中PID输出直接控制实际值。
|
||||||
|
|
||||||
|
请注意,这只是一个简单的示例程序,实际应用中可能需要根据具体需求进行调整和优化。此外,PID控制算法还需要考虑一些边界条件和特殊情况,例如积分饱和、微分先行等。因此,在实际应用中,建议根据具体需求进行深入研究和实践。
|
||||||
|
|
||||||
|
内容由AI大模型生成,仅供参考
|
||||||
|
Before Width: | Height: | Size: 128 KiB After Width: | Height: | Size: 128 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 143 KiB |
|
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 178 KiB |
|
Before Width: | Height: | Size: 217 KiB After Width: | Height: | Size: 217 KiB |
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 146 KiB After Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 196 KiB After Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 138 KiB After Width: | Height: | Size: 138 KiB |
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 136 KiB |
|
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 176 KiB |
|
Before Width: | Height: | Size: 88 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 125 KiB |
|
Before Width: | Height: | Size: 144 KiB After Width: | Height: | Size: 144 KiB |
@@ -1,44 +1,50 @@
|
|||||||
|
---
|
||||||
|
tags:
|
||||||
|
- vivado
|
||||||
|
- school
|
||||||
|
---
|
||||||
|
|
||||||
# Vivado使用乘法器、除法器IP核实现乘除取余仿真
|
# Vivado使用乘法器、除法器IP核实现乘除取余仿真
|
||||||
### 环境
|
### 环境
|
||||||
**Vivado 20.2**
|
**Vivado 20.2**
|
||||||
## 添加并配置IP核
|
## 添加并配置IP核
|
||||||
1. 打开vivado,找到对应IP核,如下图
|
1. 打开vivado,找到对应IP核,如下图
|
||||||

|

|
||||||
2. 先双击除法器IP核进入配置页面,如下图
|
2. 先双击除法器IP核进入配置页面,如下图
|
||||||

|

|
||||||

|

|
||||||
除法器配置默认即可,点击OK;后弹出界面,点击Generate
|
除法器配置默认即可,点击OK;后弹出界面,点击Generate
|
||||||
如下图即配置完成
|
如下图即配置完成
|
||||||

|

|
||||||
3. 配置乘法器IP核
|
3. 配置乘法器IP核
|
||||||

|

|
||||||
上图使用十六位有符号数与十六位无符号数进行运算
|
上图使用十六位有符号数与十六位无符号数进行运算
|
||||||

|

|
||||||
上图输出32位,间隔一个周期得到结果(电脑性能不佳可适当增加)
|
上图输出32位,间隔一个周期得到结果(电脑性能不佳可适当增加)
|
||||||
4. 如下图即配置完成
|
4. 如下图即配置完成
|
||||||

|

|
||||||
## 添加并编写仿真代码文件
|
## 添加并编写仿真代码文件
|
||||||
1. 选择一个文件夹,创建例如ipcore_test.v文件
|
1. 选择一个文件夹,创建例如ipcore_test.v文件
|
||||||
2. 添加文件到vivado
|
2. 添加文件到vivado
|
||||||

|

|
||||||

|

|
||||||
找到自己创建的.v文件路径并添加
|
找到自己创建的.v文件路径并添加
|
||||||
3. 完成如下图
|
3. 完成如下图
|
||||||

|

|
||||||
4. 复制示例代码
|
4. 复制示例代码
|
||||||

|

|
||||||
双击打开.veo 示例代码文件
|
双击打开.veo 示例代码文件
|
||||||

|

|
||||||
复制上图红框中的代码到自己的仿真文件,如下图(我这是外部编辑器,vivado自带编辑器同理)
|
复制上图红框中的代码到自己的仿真文件,如下图(我这是外部编辑器,vivado自带编辑器同理)
|
||||||

|

|
||||||
上图的module与endmodule需要自己添加
|
上图的module与endmodule需要自己添加
|
||||||
如下图,可以看到,除法器IP核在你自己的代码文件之下,表示被正确调用
|
如下图,可以看到,除法器IP核在你自己的代码文件之下,表示被正确调用
|
||||||

|

|
||||||
乘法器同理,打开.veo文件复制代码
|
乘法器同理,打开.veo文件复制代码
|
||||||

|

|
||||||

|

|
||||||
示例代码复制完成后如下图,这里我更改了实例名称(u_ 开头,不改没影响)
|
示例代码复制完成后如下图,这里我更改了实例名称(u_ 开头,不改没影响)
|
||||||

|

|
||||||
5. 最后自己补全仿真代码,我这里这样写
|
5. 最后自己补全仿真代码,我这里这样写
|
||||||
```verilog
|
```verilog
|
||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
@@ -105,8 +111,8 @@ endmodule
|
|||||||
|
|
||||||
6. 结果分析
|
6. 结果分析
|
||||||
选中除B之外的所有变量,调整为有符号的十进制,B调整为无符号的十进制数
|
选中除B之外的所有变量,调整为有符号的十进制,B调整为无符号的十进制数
|
||||||

|

|
||||||
下图可以看到,乘法器得到数据(一开始),在第一个周期得到结果,除法器得到数据,在第二十个周期得到结果
|
下图可以看到,乘法器得到数据(一开始),在第一个周期得到结果,除法器得到数据,在第二十个周期得到结果
|
||||||

|

|
||||||
|
|
||||||
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
tags:
|
tags:
|
||||||
- school
|
- school
|
||||||
|
- 文献
|
||||||
---
|
---
|
||||||
|
|
||||||
# 十五篇
|
# 十五篇
|
||||||
|
|||||||