活动介绍

#include<stdio.h> #include<math.h> int count=1; double cos_x(x) ; int main() { float x; double cosx; scanf("%f",&x); cosx=cos_x(x); printf("cos(%.6f)=%lf count=%d\n",x,cosx,count); return 0; } double cos_x(float x) { double sum =1,t=1; int n=0; while(fabs(t)<=1.e-5) { n=n+2; t=- x*x/n/(n-1); sum=sum+t; count++; } return(sum); }改错

时间: 2024-03-25 11:35:53 浏览: 106
这段代码存在几个问题,我来一一指出并改正。 1. 函数 `cos_x` 的参数类型应该是 `float` 而不是无类型的 `x`。 2. 在 `while` 循环中,条件判断应该是 `fabs(t)>=1.e-5`,因为我们要一直循环直到 `t` 足够小才停止。 3. 在 `while` 循环中,应该先更新 `t` 再更新 `sum`,否则会导致结果错误。 修改后的代码如下: ```c #include<stdio.h> #include<math.h> int count=1; double cos_x(float x); int main() { float x; double cosx; scanf("%f",&x); cosx=cos_x(x); printf("cos(%.6f)=%lf count=%d\n",x,cosx,count); return 0; } double cos_x(float x) { double sum =1,t=1; int n=0; while(fabs(t)>=1.e-5) { n=n+2; t=- t*x*x/n/(n-1); sum=sum+t; count++; } return(sum); } ``` 修改后的代码已经能够正确计算 `cos(x)` 并输出运算次数 `count`。
相关问题

#include<stdlib.h> #include <stdio.h> #include <math.h> #define PI 3.1415926 double f(double x) { return exp(x)cos(4x); // 定义被积函数 } double simpson(double a, double b) { int n = 1000; // 分割区间的个数 double h = (b - a) / n; double sum = 0; for (int i = 0; i < n; i++) { double x1 = a + i * h; double x2 = a + (i + 1) * h; sum += f(x1) + 4 * f((x1 + x2) / 2) + f(x2); } return sum * h / 6; } int main() { double a = 0, b = PI; // 积分区间 [a, b] double result = simpson(a, b); printf("The result is: %lf\n", result); system("pause"); return 0; }写出计算这个代码的函数调用次数的C语言代码

可以在原代码基础上加入计数器,用于统计函数调用的次数,代码如下: ``` #include<stdlib.h> #include<stdio.h> #include<math.h> #define PI 3.1415926 int f_call_count = 0; // 函数f(x)的调用次数计数器 double f(double x) { f_call_count++; // 每次调用函数f(x)时计数器加1 return exp(x)cos(4x); // 定义被积函数 } double simpson(double a, double b) { int n = 1000; // 分割区间的个数 double h = (b - a) / n; double sum = 0; for (int i = 0; i < n; i++) { double x1 = a + i * h; double x2 = a + (i + 1) * h; sum += f(x1) + 4 * f((x1 + x2) / 2) + f(x2); } return sum * h / 6; } int main() { double a = 0, b = PI; // 积分区间 [a, b] double result = simpson(a, b); printf("The result is: %lf\n", result); printf("The function f(x) is called %d times.\n", f_call_count); system("pause"); return 0; } ``` 运行程序后,会输出计算结果和函数 `f(x)` 的调用次数。

(2020等级考1)调试要求:下列程序包含3个错误,请按题中的功能要求,调试并修改该程序(在所修改语句后加/∗∗∗∗∗∗∗/字样的注释),使其运行能得到正确的结果。 功能说明: 利用泰勒级数 1.jpg 计算cos(x)的值(x是弧度),要求最后一项的绝对值小于10-5,并统计出此时累加了多少项。 输入样例1: 0 输出样例1: cos(0.000000)=1.000000 count=2 输入样例2: 1.0471975 输出样例2: cos(1.047197)=0.500000 count=6 带错误源程序: #include<stdio.h> #include<math.h> int count=1; double cos_x(x) ; int main() { float x; double cosx; scanf("%f",&x); cosx=cos_x(x); printf("cos(%.6f)=%lf count=%d\n",x,cosx,count); return 0; } double cos_x(float x) { double sum =1,t=1; int n=0; while(fabs(t)<=1.e-5) { n=n+2; t=- x*x/n/(n-1); sum=sum+t; count++; } return(sum); }

修改后的程序如下: ```c #include <stdio.h> #include <math.h> int count = 1; double cos_x(float x); int main() { float x; double cosx; scanf("%f", &x); cosx = cos_x(x); printf("cos(%.6f)=%.6f count=%d\n", x, cosx, count); return 0; } double cos_x(float x) { double sum = 1, t = 1; int n = 0; while (fabs(t) >= 1e-5) { // 修改绝对值的判断条件 n += 2; t = -t * x * x / n / (n - 1); // 修改计算公式 sum += t; count++; } return sum; } ``` 代码中的错误有: 1. 在 main 函数中,输入的参数类型应该为 float,而不是 double。 2. 在 while 循环中,判断绝对值大小的条件应该是 fabs(t) >= 1e-5,而不是 fabs(t) <= 1.e-5。 3. 在计算 cos(x) 的公式中,应该将 x*x 放在分母的后面,即 -t * x * x / n / (n - 1)。
阅读全文

相关推荐

/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2025 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "adc.h" #include "dma.h" #include "spi.h" #include "tim.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "BL0942.h" #include <stdio.h> #include <math.h> #define M_PI 3.14159265358979323846 #include <stdbool.h> #include "oled.h" #define SAMPLE_RATE 2500 // 采样率2500Hz #define SAMPLE_POINTS 200 // 每个周期50个采样点 #define SHUNT_RESISTOR 100.0f // 采样电阻100Ω #define CT_RATIO 2000.0f // 互感器变比2000:1 // 继电器控制阈值设定 #define THRESHOLD_MAX 8.11f #define THRESHOLD_MIN 0.0f #define MIN_OPERATE_CURRENT 0.1f // 最小操作电流(0.1A) //应用电能计算上 #define MIN_CURRENT 0.1f #define POWER_DEADZONE 0.5f // 0.1W以下视为无效 float voltage_offset = 0.0f; float current_A_offset = 0.0f, current_B_offset = 0.0f, current_C_offset = 0.0f; /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ // 添加ADC相关定义 #define ADC_CHANNELS 4 // 4个ADC通道 uint16_t adc_buf0[ADC_CHANNELS * SAMPLE_POINTS]= {0}; // DMA缓冲区 // ADC校准参数 float vref = 3.3f; // ADC参考电压 float offset = 1.65f; // 硬件偏置电压 float voltage_rms; // 添加相位差存储变量和标志位 float phase_diff_A, phase_diff_B, phase_diff_C; volatile bool data_ready = false; // 电压/电流值存储数组(真实值) float current_A[SAMPLE_POINTS]; float current_B[SAMPLE_POINTS]; float current_C[SAMPLE_POINTS]; float voltage[SAMPLE_POINTS]; // 添加滤波数组 float voltage_filtered[SAMPLE_POINTS]; float current_A_filtered[SAMPLE_POINTS]; float current_B_filtered[SAMPLE_POINTS]; float current_C_filtered[SAMPLE_POINTS]; static const char *loadType = "Non-resistive load"; // 初始值设为非阻性 // 新增电能计量相关全局变量 typedef struct { float active_energy; // 有功电能(单位:kWh) float apparent_energy; // 视在电能(单位:kVAh) float power_factor; // 实时功率因数 } EnergyMeter; EnergyMeter p_A, p_B, p_C; // 各相电能计量 float total_energy = 0.0f; // 总累计电能(kWh) float delta_t = 1.0f / SAMPLE_RATE; // 采样时间间隔(秒) float V_line; /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ //static uint8_t valid_count_A = 0; //static bool relay_engaged_A = false; //static uint8_t valid_count = 0; //static bool relay_engaged = false; static uint8_t valid_count_C = 0; //static bool relay_engaged_C = false; #define REQUIRED_CONSECUTIVE_HITS 3 // 需要连续5次有效点 //继电器定时切换 //static uint32_t relay_trigger_time_A = 0; //static bool relay_delay_active_A = false; //static uint32_t relay_trigger_time = 0; //static bool relay_delay_active = false; //static uint32_t relay_trigger_time_C = 0; //static bool relay_delay_active_C = false; #define RELAY_OPERATION_TIME 10000 // 10秒延时,修改这个修改继电器状态从断开到闭合的时间 //断电次数 int Power_Outage_Count_A = 0; int Power_Outage_Count_B = 0; int Power_Outage_Count_C = 0; #define POWER_THRESHOLD_A 2500.0f // A相功率阈值2500W #define POWER_THRESHOLD_B 2500.0f // B相功率阈值2500W #define POWER_THRESHOLD_C 2500.0f // C相功率阈值2500W /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ static uint8_t cmdbuf[2]= {0x58,0xaa}; uint8_t test[50]; uint8_t flag; BL0942_Data meter_data; /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ /* USER CODE BEGIN PV */ char display_buf[32]; // 用于格式化的显示缓冲区 float phase_A_1; float phase_B_1; float phase_C_1; float current_A_rms; float current_B_rms; float current_C_rms; bool OLED__Clear = 1; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); /* USER CODE BEGIN PFP */ float CalculatePhaseDifferenceByPeak(float *voltage, float *current, int length); /* USER CODE END PFP */ /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ // OLED显示浮点数函数 void OLED_ShowFloat(uint8_t x, uint8_t y, float num, uint8_t size) { sprintf(display_buf, "%.2f", num); // 保留1位小数 OLED_ShowString(x, y, (uint8_t*)display_buf, size, 1); } // OLED显示带标签的测量值 void DisplayMeasurements(void) { // 显示C相相位差 OLED_ShowChinese(0,0,0,16,1);//相 OLED_ShowChinese(18,0,1,16,1);//位 OLED_ShowChinese(36,0,2,16,1);//差 OLED_ShowChar(54, 0, ':', 16, 1); // 直接传入字符':' if (isnan(phase_C_1)) { OLED_ShowString(72, 2, (uint8_t*)"nan", 16, 1); if(OLED__Clear == 1) { OLED_Clear(); OLED__Clear = 0; } } else { OLED_ShowFloat(72, 2, phase_C_1, 16); OLED__Clear = 1; } // OLED_ShowFloat(72, 2, phase_C_1, 16); OLED_ShowChinese(0,17,3,16,1); OLED_ShowChinese(18,17,4,16,1); OLED_ShowChinese(36,17,5,16,1); OLED_ShowChar(54, 17, ':', 16, 1); OLED_ShowFloat(72, 17, current_C_rms, 16); } // 平滑滤波函数 void SmoothFilter(float *input, float *output, int length) { const int window_size = SAMPLE_POINTS / 10; // const int window_size = 5; // 滑动窗口大小 const int half_window = window_size / 2; for(int i = 0; i < length; i++) { double sum = 0.0; int count = 0; // 滑动窗口累加 for(int j = -half_window; j <= half_window; j++) { int idx = i + j; if(idx >= 0 && idx < length) { sum += input[idx]; count++; } } // 计算平均值并存储结果 output[i] = sum / (double)count; } } // 相位差计算函数 float CalculatePhaseDifference(float *voltage, float *current, int length) { float v_zero = -1.0f; float i_zero = -1.0f; // 电流有效值检查 float sum_sq = 0.0f; for(int i=0; i<length; i++) { sum_sq += current[i] * current[i]; } float current_rms = sqrtf(sum_sq / length); // 电流小于阈值直接返回NAN if (current_rms < 0.05f) { // 阈值根据噪声调整 return NAN; } // 电压过零点检测(负→正,带趋势确认) for(int i=1; i < length-2; i++) { if(voltage[i] <0 && voltage[i+1] >=0) { if(voltage[i-1] <0 && voltage[i+2] >0) { // 趋势条件放宽 float delta = voltage[i+1] - voltage[i]; float fraction = (0 - voltage[i]) / delta; v_zero = i + fraction; break; } } } // 电流过零点检测(负→正,带趋势确认) for(int i=1; i < length-2; i++) { if(current[i] <0 && current[i+1] >=0) { if(current[i-1] <0 && current[i+2] >0) { float delta = current[i+1] - current[i]; float fraction = (0 - current[i]) / delta; i_zero = i + fraction; break; } } } if(v_zero < 0 || i_zero < 0) { return NAN; } // 计算原始相位差(每个采样点7.2度) float phase_diff = (i_zero - v_zero) * 7.2f; // 相位归一化 if(phase_diff > 180.0f) { phase_diff -= 360.0f; } else if(phase_diff < -180.0f) { phase_diff += 360.0f; } return phase_diff; } /** * @brief 通过检测电压和电流信号的绝对峰值点计算相位差 * @param voltage: 已滤波的电压信号数组 * @param current: 已滤波的电流信号数组 * @param length: 数组长度(采样点数) * @retval 相位差(单位:度),正值表示电流滞后电压,负值表示电流超前 * @note 每个采样点对应7.2°(360°/50个采样点) * 当电流有效值过小时返回NAN(无效值) */ float CalculatePhaseDifferenceByPeak(float *voltage, float *current, int length) { float sum_sq = 0.0f; // 1. 计算电流有效值用于有效性检查 for(int i=0; i<length; i++) { sum_sq += current[i] * current[i]; } float current_rms = sqrtf(sum_sq / length); if (current_rms < 0.01f) { // 电流小于0.05A视为无效 return NAN; } // 2. 寻找电压绝对值的峰值点 int v_peak_index = 0; float v_max_abs = fabsf(voltage[0]); for(int i=1; i<length; i++) { float abs_val = fabsf(voltage[i]); if(abs_val > v_max_abs) { v_max_abs = abs_val; v_peak_index = i; } } // 3. 寻找电流绝对值的峰值点 int i_peak_index = 0; float i_max_abs = fabsf(current[0]); for(int i=1; i<length; i++) { float abs_val = fabsf(current[i]); if(abs_val > i_max_abs) { i_max_abs = abs_val; i_peak_index = i; } } // 4. 计算原始相位差(每个采样点7.2°) float phase_diff = (i_peak_index - v_peak_index) * 7.2f; // 5. 相位归一化到[-180°,180°] if(phase_diff > 180.0f) { phase_diff -= 360.0f; } else if(phase_diff < -180.0f) { phase_diff += 360.0f; } return phase_diff; } // RMS计算函数 float CalculateTrueCurrentRMS(float *voltage_samples) { float sum_squares = 0.0f; // 1. 计算电压平方和 for(int i=0; i<SAMPLE_POINTS; i++) { sum_squares += voltage_samples[i] * voltage_samples[i]; } // 2. 计算电压有效值(RMS) voltage_rms = sqrtf(sum_squares / SAMPLE_POINTS); // 3. 计算真实电流有效值 // 电流计算流程:电压有效值 → 二次侧电流 → 一次侧电流 float current_secondary = voltage_rms / SHUNT_RESISTOR; // 二次侧电流 float current_primary = current_secondary * CT_RATIO; // 一次侧电流 return current_primary; } // 数据处理函数 void ProcessADCData(uint16_t *buf) { /*-------------------------------------------------------相位差计算部分-------------------------------------------------------*/ // ADC原始数据转换 for(int i=0; i<SAMPLE_POINTS; i++) { current_A[i] = -((buf[i*ADC_CHANNELS + 0] - 2048) * vref / 4095); // 添加负号反转信号 current_B[i] = -((buf[i*ADC_CHANNELS + 1] - 2048) * vref / 4095); // 添加负号反转信号 current_C[i] = -((buf[i*ADC_CHANNELS + 2] - 2048) * vref / 4095); // 添加负号反转信号 voltage[i] = ((buf[i*ADC_CHANNELS + 3] - 2048) * vref / 4095); } // 信号滤波 SmoothFilter(voltage, voltage_filtered, SAMPLE_POINTS); SmoothFilter(current_A, current_A_filtered, SAMPLE_POINTS); SmoothFilter(current_B, current_B_filtered, SAMPLE_POINTS); SmoothFilter(current_C, current_C_filtered, SAMPLE_POINTS); // 相位差计算 float phase_A = CalculatePhaseDifference(voltage_filtered, current_A_filtered, SAMPLE_POINTS); float phase_B = CalculatePhaseDifference(voltage_filtered, current_B_filtered, SAMPLE_POINTS); float phase_C = CalculatePhaseDifference(voltage_filtered, current_C_filtered, SAMPLE_POINTS); // 修改为峰值检测法: phase_A_1 = CalculatePhaseDifferenceByPeak(voltage_filtered, current_A_filtered, SAMPLE_POINTS); phase_B_1 = CalculatePhaseDifferenceByPeak(voltage_filtered, current_B_filtered, SAMPLE_POINTS); phase_C_1 = CalculatePhaseDifferenceByPeak(voltage_filtered, current_C_filtered, SAMPLE_POINTS); // 电流有效值计算 current_A_rms = CalculateTrueCurrentRMS(current_A_filtered); current_B_rms = CalculateTrueCurrentRMS(current_B_filtered); current_C_rms = CalculateTrueCurrentRMS(current_C_filtered); // 电压、电流对应的采样电阻电压值 // printf("采样点 | 电压(V) | 电流A(V) | 电流B(V) | 电流C(V)\r\n"); for(int i=0; i<SAMPLE_POINTS; i++) { printf("[%02d] %7.3f %7.3f %7.3f %7.3f\r\n", i, voltage_filtered[i], current_A_filtered[i], current_B_filtered[i], current_C_filtered[i]); } // 输出:相位差,电流有效值 // printf("LA:%.1f°/%.2fA LB:%.1f°/%.2fA LC:%.1f°/%.2fA\n", // phase_A, current_A_rms, // phase_B, current_B_rms, // phase_C, current_C_rms); // 输出:峰值计算相位差,过零电计算相位差,电流有效值 // printf("LA:峰值相位差=%.1f° 过零相位差=%.1f°/%.2fA LB:峰值相位差=%.1f° 过零相位差=%.1f°/%.2fA LC:峰值相位差=%.1f° 过零相位差=%.1f°/%.2fA\n", // phase_A_1, phase_A, current_A_rms, // phase_B_1, phase_B, current_B_rms, // phase_C_1, phase_C, current_C_rms); /*-------------------------------------------------------非BL0942电能计量部分-------------------------------------------------------*/ // A、B、C三回路电能计量 for(int i=0; i<SAMPLE_POINTS; i++) { //数据遍历处理 // 仅当A电流有效值达标时积分 if(current_A_rms >= MIN_CURRENT + 0.3) { //电流有效性检测 V_line = (voltage_filtered[i] - voltage_offset) * 100.0f; //电压信号处理 float I_A_primary = (current_A_filtered[i]/SHUNT_RESISTOR - current_A_offset) * CT_RATIO; //电流信号处理 float P_inst_A = V_line * I_A_primary; //瞬时功率计算 // 死区过滤 if(fabsf(P_inst_A) > POWER_DEADZONE) { p_A.active_energy += P_inst_A * delta_t / 3600000.0f; //电能累加计算 } } // 仅当B电流有效值达标时积分 if(current_B_rms >= MIN_CURRENT) { V_line = (voltage_filtered[i] - voltage_offset) * 100.0f; float I_B_primary = (current_B_filtered[i]/SHUNT_RESISTOR - current_B_offset) * CT_RATIO; float P_inst_B = V_line * I_B_primary; // 死区过滤 if(fabsf(P_inst_B) > POWER_DEADZONE) { p_B.active_energy += P_inst_B * delta_t / 3600000.0f; } } // 仅当C电流有效值达标时积分 if(current_C_rms >= MIN_CURRENT) { V_line = (voltage_filtered[i] - voltage_offset) * 100.0f; float I_C_primary = (current_C_filtered[i]/SHUNT_RESISTOR - current_C_offset) * CT_RATIO; float P_inst_C = V_line * I_C_primary; // 死区过滤 if(fabsf(P_inst_C) > POWER_DEADZONE) { p_C.active_energy += P_inst_C * delta_t / 3600000.0f; } } } // 4. 计算功率因数(使用相位差) p_A.power_factor = cosf(fabsf(phase_A) * M_PI / 180.0f); p_B.power_factor = cosf(fabsf(phase_B) * M_PI / 180.0f); p_C.power_factor = cosf(fabsf(phase_C_1) * M_PI / 180.0f); // 5. 计算视在电能 p_A.apparent_energy += (current_A_rms * V_line) * delta_t / 3600.0f; p_B.apparent_energy += (current_B_rms * V_line) * delta_t / 3600.0f; p_C.apparent_energy += (current_C_rms * V_line) * delta_t / 3600.0f; // // 6. 更新总电能(转换为kWh) total_energy = (p_A.active_energy + p_B.active_energy + p_C.active_energy); // 7. 电能数据输出 // printf("\n电能计量:"); // printf("\nLA: %.9fkWh (PF=%.2f)", p_A.active_energy, p_A.power_factor); // printf("\nLB: %.9fkWh (PF=%.2f)", p_B.active_energy, p_B.power_factor); // printf("\nLC: %.9fkWh (PF=%.2f)", p_C.active_energy, p_C.power_factor); // printf("\n总电能: %.9fkWh\n", total_energy); if (fabsf(p_C.power_factor) >= 0.99f && fabsf(p_C.power_factor) <= 1.0f) { HAL_Delay(100); if (fabsf(p_C.power_factor) >= 0.99f && fabsf(p_C.power_factor) <= 1.0f) { valid_count_C++; if (valid_count_C > REQUIRED_CONSECUTIVE_HITS && (fabsf(p_C.power_factor) >= 0.99f && fabsf(p_C.power_factor) <= 1.0f)) { OLED_Clear(); OLED_ShowChinese(0,0,6,16,1);//阻 OLED_ShowChinese(18,0,7,16,1);//性 OLED_ShowChinese(36,0,8,16,1);//负 OLED_ShowChinese(52,0,9,16,1);//载 OLED_ShowChinese(70,0,6,16,1);//阻 OLED_ShowChinese(88,0,7,16,1);//性 OLED_ShowChinese(106,0,8,16,1);//负 OLED_ShowChinese(124,0,9,16,1);//载 loadType = "Resistive load"; // 设置为阻性负载 OLED_ShowChinese(0,17,6,16,1);//阻 OLED_ShowChinese(18,17,7,16,1);//性 OLED_ShowChinese(36,17,8,16,1);//负 OLED_ShowChinese(52,17,9,16,1);//载 OLED_ShowChinese(70,17,6,16,1);//阻 OLED_ShowChinese(88,17,7,16,1);//性 OLED_ShowChinese(106,17,8,16,1);//负 OLED_ShowChinese(124,17,9,16,1);//载 OLED_Refresh(); valid_count_C = 0; // HAL_Delay(100); // OLED_Clear(); } // if (valid_count_C > REQUIRED_CONSECUTIVE_HITS) { // valid_count_C = REQUIRED_CONSECUTIVE_HITS; // } } } else{ valid_count_C = 0; OLED_Clear(); } /*-------------------------------------------------------C相控制条件判断-------------------------------------------------------*/ // bool condition_met_C = (!isnan(phase_C)) && // (current_C_rms > MIN_OPERATE_CURRENT) && // (phase_C > THRESHOLD_MIN) && // (phase_C < THRESHOLD_MAX); // // 状态机逻辑 // if (condition_met_C) { //// HAL_Delay(100); // if (condition_met_C) { // // 条件满足时增加计数器 // valid_count_C++; // // 达到阈值,断开继电器 // if (valid_count_C >= REQUIRED_CONSECUTIVE_HITS && !relay_engaged_C) { // HAL_GPIO_WritePin(GPIOC, K1P_Pin, GPIO_PIN_SET); // HAL_GPIO_WritePin(GPIOC, K1N_Pin, GPIO_PIN_RESET); // relay_engaged_C = true; // Power_Outage_Count_C++; // } // // 记录触发时间并激活延时标志 // relay_trigger_time_C = HAL_GetTick(); // relay_delay_active_C = true; // // 防止计数器溢出 // if (valid_count_C > REQUIRED_CONSECUTIVE_HITS) { // valid_count_C = REQUIRED_CONSECUTIVE_HITS; // } // } // } // else { // // 条件不满足时重置计数器并闭合继电器 // valid_count_C = 0; // if (relay_delay_active_C && (HAL_GetTick() - relay_trigger_time_C >= RELAY_OPERATION_TIME)) { // HAL_GPIO_WritePin(GPIOC, K1P_Pin, GPIO_PIN_RESET); // HAL_GPIO_WritePin(GPIOC, K1N_Pin, GPIO_PIN_SET); // relay_engaged_C = false; // relay_delay_active_C = false; // } // } } /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DMA_Init(); MX_SPI2_Init(); MX_UART4_Init(); MX_USART1_UART_Init(); MX_USART2_UART_Init(); MX_ADC1_Init(); MX_TIM3_Init(); MX_TIM2_Init(); /* USER CODE BEGIN 2 */ HAL_UARTEx_ReceiveToIdle_DMA(&huart2, test, 50); HAL_TIM_Base_Start(&htim2); HAL_TIM_Base_Start(&htim3); // 初始化电能计量结构体 p_A.active_energy = 0; p_A.apparent_energy = 0; p_A.power_factor = 1.0; p_B.active_energy = 0; p_B.apparent_energy = 0; p_B.power_factor = 1.0; p_C.active_energy = 0; p_C.apparent_energy = 0; p_C.power_factor = 1.0; HAL_ADCEx_Calibration_Start(&hadc1); // 重新执行ADC校准 // 启用ADC DMA HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buf0, ADC_CHANNELS*SAMPLE_POINTS); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ OLED_Init(); OLED_ColorTurn(0); // 正常显示 OLED_DisplayTurn(0); // 不翻转屏幕 OLED_Clear(); while (1) {loadType = "Non-resistive load"; ProcessADCData(adc_buf0); if (flag==1) { flag=0; meter_data=Data_Processing(test); } HAL_UART_Transmit_DMA(&huart2,cmdbuf,2); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ // HAL_GPIO_WritePin(GPIOC, K1P_Pin, GPIO_PIN_RESET); // HAL_GPIO_WritePin(GPIOC, K1N_Pin, GPIO_PIN_SET); // HAL_Delay(500); // HAL_GPIO_WritePin(GPIOC, K1P_Pin, GPIO_PIN_SET); // HAL_GPIO_WritePin(GPIOC, K1N_Pin, GPIO_PIN_RESET); // HAL_Delay(500); // 显示测量值 DisplayMeasurements(); OLED_Refresh(); // HAL_Delay(50); // OLED_Clear(); HAL_Delay(50); } /* USER CODE END 3 */ } /** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; RCC_OscInitStruct.HSEState = RCC_HSE_ON; RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { Error_Handler(); } PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC; PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ //USART2中断回调函数 void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { if(huart->Instance == USART2) { if (Size==23) { flag=1; } HAL_UARTEx_ReceiveToIdle_DMA(&huart2, test, 50); } } //ADC中断回调函数 void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { static uint32_t last_tick = 0; uint32_t current_tick = HAL_GetTick(); // 计算实际采样间隔(应对可能的时序漂移) if (last_tick != 0) { delta_t = ((current_tick - last_tick) / 1000.0f) + 0.027f; } last_tick = current_tick; } /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(uint8_t *file, uint32_t line) { /* USER CODE BEGIN 6 */ /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* USER CODE END 6 */ } #endif /* USE_FULL_ASSERT */ 如何检测负载时阻性负载还是非阻性负载。如果接入多个负载,其中有阻性负载,也有非阻性负载,又该如何分别出阻性负载

function constrained_lspia_b_spline() clc;clear; close all % 生成半圆测试数据(2000个点) theta = linspace(0, pi, 1000)'; X = [cos(theta), sin(theta)]; % 无噪声的半圆数据 X = [X; [-ones(1, 1000);linspace(0, -1, 1000)].']; X = [X; [cos(-theta), sin(-theta)]-[2, 1]] ; % 初始化参数 % n = 2000; % 数据点数量 n = length(X); m = 50; % 控制点数量 k = 3; % 三次B样条 max_iter = 1000;% 最大迭代次数 % 1. 参数化(累积弦长法) chords = vecnorm(diff(X), 2, 2); u = [0; cumsum(chords)/sum(chords)]; % 2. 初始化控制点(带约束) P = initialize_control_points(X, m); p_1 = P(1:2,:); p_n = P(end-1:end,:); [tlist] = GetParaT(P);%节点序列 % 3. 创建带约束的节点向量 knots = constrained_knot_vector(tlist, k, m); % 4. 预计算基函数矩阵(稀疏存储) N = zeros(n, m); for i = 1:n span = findSpan(u(i), knots, m); basis = basisFunctions(u(i), span, knots, k); N(i, span-k:span) = basis; end % 5. LSPIA迭代(带约束更新) lambda = 1.6; % 松弛因子 for iter = 1:max_iter % 计算当前拟合点 Q = N * P; % 计算残差向量 R = X - Q; % 计算控制点增量 deltaP = (N' * R) * lambda/n; % 带约束的更新:固定起点和终点位置及切向量 P = P + deltaP; P(1:2,:) = p_1; P(end-1:end,:) = p_n; % 检查收敛条件 norm(deltaP) if norm(deltaP) < 1e-3 break; end end iter % 6. 结果验证和可视化 % 验证端点约束 verify_endpoint_constraints(X, N, P, knots, k); % 生成拟合曲线评估点 u_eval = linspace(0, 1, 1000); curve = zeros(length(u_eval), 2); for i = 1:length(u_eval) span = findSpan(u_eval(i), knots, m); basis = basisFunctions(u_eval(i), span, knots, k); curve(i,:) = basis * P(span-k:span, :); end % 可视化结果 figure; plot(X(:,1), X(:,2), '.-', 'MarkerSize', 4, 'Color', [0.7 0.7 0.7]); hold on; plot(P(:,1), P(:,2), 'ro-', 'LineWidth', 1.5); plot(curve(:,1), curve(:,2), 'b-', 'LineWidth', 2); legend('原始数据', '控制点', '拟合曲线'); title(sprintf('带约束的LSPIA B样条拟合 (%d次迭代)', iter)); axis equal; grid on; end % 带约束的初始化控制点 function P = initialize_control_points(X, m) % 初始化控制点(均匀采样) % idx = round(linspace(1, size(X,1), m)); % P = X(idx, :) + [0, 0]; n = length(X); total_length = 0; for i = 1 : n-1 total_length = total_length + norm(X(i+1, :) - X(i,:)); end step = total_length / (m-1); curp = 0; P(1, :) = X(1, :); for j = 2 : m len = 0; for i = 1 : n-1 len = len + norm(X(i+1, :) - X(i,:)); if curp + step < len P(j,:) = X(i,:); curp = curp + step; break; end end end P = [P; X(end, :)]; % 端点约束:起点和终点位置及切向量 start_point = X(1, :); end_point = X(end, :); start_tangent = X(2, :) - X(1, :); % 起点切向量 (0,1) end_tangent = X(end, :) - X(end - 1, :); % 终点切向量 (0,-1) start_tangent = start_tangent / norm(start_tangent); end_tangent = end_tangent / norm(end_tangent); % 应用端点约束 P(1, :) = start_point; P(end, :) = end_point; % 应用切向量约束(通过第二个和倒数第二个控制点) P(2, :) = start_point + start_tangent * 0.1; % 调整系数以控制切向量长度 P(end-1, :) = end_point - end_tangent * 0.1; end % 带端点约束的节点向量生成 function knots = constrained_knot_vector(tlist, k, m) % 创建均匀节点向量 knots = linspace(0, 1, m - k + 1); n = length(tlist); % 添加端点重复以满足插值条件 knots = [zeros(1, k), knots, ones(1, k)]; knots(m-3)=1;knots(m-2)=1;knots(m-1)=1;knots(m)=1; for j=1:n-k-1 tmp=0; for i=j:j+k-1 tmp=tmp+tlist(i+1); end knots(j+k+1)=tmp/k; end end % 端点约束验证 function verify_endpoint_constraints(X, N, P, knots, k) % 端点约束:起点和终点位置及切向量 start_point = X(1, :); end_point = X(end, :); start_tangent = X(2, :) - X(1, :); % 起点切向量 (0,1) end_tangent = X(end, :) - X(end - 1, :); % 终点切向量 (0,-1) start_tangent = start_tangent / norm(start_tangent); end_tangent = end_tangent / norm(end_tangent); % 验证起点位置 fitted_start = N(1, :) * P; position_error_start = norm(fitted_start - start_point); fprintf('起点位置误差: %.2e\n', position_error_start); % 验证终点位置 fitted_end = N(end, :) * P; position_error_end = norm(fitted_end - end_point); fprintf('终点位置误差: %.2e\n', position_error_end); % 验证起点切向量 u = 0.001; % 微小参数变化 span0 = findSpan(0, knots, size(P,1)); basis0 = basisFunctions(0, span0, knots, k); point0 = basis0 * P(span0-k:span0, :); span1 = findSpan(u, knots, size(P,1)); basis1 = basisFunctions(u, span1, knots, k); point1 = basis1 * P(span1-k:span1, :); fitted_tangent = (point1 - point0) / u; fitted_tangent = fitted_tangent / norm(fitted_tangent); tangent_error_start = acos(dot(fitted_tangent, start_tangent/norm(start_tangent))); fprintf('起点切向量角度误差: %.2f 度\n', rad2deg(tangent_error_start)); % 验证终点切向量 u_end = 1 - u; span_end0 = findSpan(1, knots, size(P,1)); basis_end0 = basisFunctions(1, span_end0, knots, k); point_end0 = basis_end0 * P(span_end0-k:span_end0, :); span_end1 = findSpan(u_end, knots, size(P,1)); basis_end1 = basisFunctions(u_end, span_end1, knots, k); point_end1 = basis_end1 * P(span_end1-k:span_end1, :); fitted_tangent_end = (point_end0 - point_end1) / u; fitted_tangent_end = fitted_tangent_end / norm(fitted_tangent_end); tangent_error_end = acos(dot(fitted_tangent_end, end_tangent/norm(end_tangent))); fprintf('终点切向量角度误差: %.2f 度\n', rad2deg(tangent_error_end)); end % 计算节点区间索引 function span = findSpan(u, knots, n_ctrl) if u >= knots(n_ctrl+1) span = n_ctrl; return; end low = 1; high = n_ctrl + 1; mid = floor((low+high)/2); while (u < knots(mid)) || (u >= knots(mid+1)) if u < knots(mid) high = mid; else low = mid; end mid = floor((low+high)/2); end span = mid; end % 计算非零基函数 function N = basisFunctions(u, span, knots, k) N = zeros(1, k+1); left = zeros(1, k+1); right = zeros(1, k+1); N(1) = 1.0; for j = 1:k left(j+1) = u - knots(span+1-j); right(j+1) = knots(span+j) - u; saved = 0.0; for r = 0:j-1 temp = N(r+1)/(right(r+2)+left(j-r+1)); N(r+1) = saved + right(r+2)*temp; saved = left(j-r+1)*temp; end N(j+1) = saved; end end function [tlist] = GetParaT(Data) % 求节点序列 [n,~]=size(Data); tlist=zeros(1,n); tlist(n)=1; totlen=0; for i=1:n-1 temp=norm(Data(i+1,:)-Data(i,:)); totlen=totlen+temp; end for j=2:n-1 temp=norm(Data(j,:)-Data(j-1,:)); tlist(j)=tlist(j-1)+temp/totlen; end end 转成c语言代码

function [blks] = GetSplineBlk_1(Data,Vs,Ve,startflag,endflag) dl=0.02; [k,~]=size(Data); totpoints=[]; blks=[]; start=[Data(1,2),Data(1,3)]; Idset=[]; Numset=[]; %% 用于计算原始轨迹起点和终点对应的u值 num=0; for i=1:k if Data(i,1)==2 || Data(i,1)==3 endp=[Data(i,4),Data(i,5)]; start=[Data(i,2),Data(i,3)]; center=[Data(i,6),Data(i,7)]; theta=Data(i,8); % [~,theta,center]=GetArc(start,endp,Data(i,4),Data(i,5),Data(i,1)) ; % blockInfo(i,1)=Data(i,1); % blockInfo(i,2)=start(1);blockInfo(i,3)=start(2); % blockInfo(i,4)=endp(1);blockInfo(i,5)=endp(2); % blockInfo(i,6)=center(1);blockInfo(i,7)=center(2); % blockInfo(i,8)=(theta);blockInfo(i,9)=arcl; r=norm(center-start); if dl > r dl = r; end % dt=asin(0.5*dl/r); dt = pi / 150; ArcSplittol=r*(1-cos(dt)); [points]=SplitArc(start,endp,center,theta,Data(i,1),ArcSplittol); % totpoints=[totpoints;points(1:end-1,:)]; start=endp; % idset=[idset;Data(i,10)]; end if Data(i,1)==1 p1=start; p2=[Data(i,4),Data(i,5)]; points=DenseLine([p1;p2],dl); % totpoints=[totpoints;points(1:end-1,:)]; % blockInfo(i,1)=Data(i,1); % blockInfo(i,2)=start(1);blockInfo(i,3)=start(2); % blockInfo(i,4)=Data(i,2);blockInfo(i,5)=Data(i,3); % blockInfo(i,9)=norm(start-[Data(i,2),Data(i,3)]); start=p2; end if i==k totpoints=[totpoints;points(1:end,:)]; else totpoints=[totpoints;points(1:end-1,:)]; end [row,~]=size(totpoints); Idset=[Idset;Data(i,10)]; % num=num+row; Numset=[Numset;row]; end %% % figure; % plot(totpoints(:,1),totpoints(:,2),'r'); v1=[0,0];v2=[0,0]; % totpoints=[totpoints;points(end,:)]; k=length(totpoints); tobefit=[totpoints(1,:)]; i=1; first=1; firstspline=1; startpos=1; if k<=200 %拟合队列最大为200个点 curp=k; if startflag && endflag mode=3; elseif startflag mode=1; elseif endflag mode=2; else mode=0; end %% 样条拟合 [~,CtrlPoints,knots,tlist,~] = Fit_WithEndConstraints(totpoints,mode,Vs,Ve); %% 获取曲率波动的点t值 [blk.ulist,blk.curvlist] = BreakBSpline1(totpoints,CtrlPoints,knots); %% [blk.ids,blk.us,~] = GetIdAndUs(Idset,Numset,curp,startpos,tlist,firstspline); blk.type = 5; blk.ctrlpnt=CtrlPoints; blk.knots=knots; blks=[blks;blk]; else while i < k i=i+1; if i > Numset(num + 1) num = num + 1; end tobefit = [tobefit;totpoints(i,:)]; remain=k-i; if length(tobefit)>=200 && remain>=10 && (i == Numset(num + 1)) && (i ~= k) % 队列里大于200段,进行拟合 curp=i; if first first=0; if startflag startflag=0; mode=1; v1=Vs; else mode=0; end else v1=bsVend; mode=1; end [~,CtrlPoints,knots,tlist,bsVend]=Fit_WithEndConstraints(tobefit,mode,v1,v2); [blk.ulist,blk.curvlist] = BreakBSpline1(tobefit,CtrlPoints,knots); [blk.ids,blk.us,startpos] = GetIdAndUs(Idset,Numset,curp,startpos,tlist,firstspline); blk.type = 5; blk.ctrlpnt=CtrlPoints; blk.knots=knots; blks = [blks;blk]; tobefit=[tobefit(end,:)]; % 清空队列,只保留队列的最后一个点 firstspline=0; end if i==k % 最后一段 curp=i; if first first=0; if startflag && endflag v1=Vs;v2=Ve; mode=3; elseif endflag v2=Ve; mode=2; elseif startflag mode=1; v1=Vs; else mode=0; end else if endflag mode=3; v1=bsVend;v2=Ve; else mode=1; v1=bsVend; end end [~,CtrlPoints,knots,tlist,bsVend] = Fit_WithEndConstraints(tobefit,mode,v1,v2); [blk.ulist,blk.curvlist] = BreakBSpline1(tobefit,CtrlPoints,knots); [blk.ids,blk.us,startpos] = GetIdAndUs(Idset,Numset,curp,startpos,tlist,firstspline); blk.type = 5; blk.ctrlpnt=CtrlPoints; blk.knots=knots; blks=[blks;blk]; end end end % figure; % plot(totpoints(:,1),totpoints(:,2),'k');hold on % for i=1:length(blks) % pp=GetBsplinePoints(blks(i).ctrlpnt,blks(i).knots); % plot(pp(:,1),pp(:,2),'r'); hold on % end % grid on end

function [ulist,curvlist] = BreakBSpline1(tobefit,CtrlPoints,knots) % 分割样条曲线 [tlist] = GetParaT(tobefit); for i=1:length(tobefit) [curv(i),~,~,curv1(i)] = DiscreteCurvature(tobefit,i); % 计算离散点曲率 end curv = abs(curv); ulist(1) = 0; curvlist(1) = CalBSplineCurvature(0,CtrlPoints,knots); % 计算样条曲线曲率 i=1;k=1; index(k)=i; while i <= length(curv)-2 i=i+1; if (curv(i)-curv(i-1) > 1e-4) && (curv(i)-curv(i+1) > 1e-4) % 曲率波动大于1e-4的序号 k=k+1; index(k)=i; end % precurv=CalBSplineCurvature(tlist(i-1),CtrlPoints,knots); % curvi=CalBSplineCurvature(tlist(i),CtrlPoints,knots); % nextcuv=CalBSplineCurvature(tlist(i+1),CtrlPoints,knots); % if (curvi-precurv>1e-4) && (curvi-nextcuv>1e-4) % k=k+1; % index(k)=i; % end end ulist=[ulist,1]; index = [index,length(tobefit)]; % curv_end=CalBSplineCurvature(1,CtrlPoints,knots); % curvlist=[curvlist,curv_end]; % [pos] = GetBsplinePoints(CtrlPoints,knots); % 样条细化成1000点 % figure; % plot(tobefit(:,1),tobefit(:,2),'r');hold on % plot(pos(:,1),pos(:,2),'k');hold on % grid on % for i=1:length(index) % plot(tobefit(index(i),1),tobefit(index(i),2),'b*');hold on % end num = length(index); for i=1:num ulist(i) = tlist(index(i)); curvlist(i) = CalBSplineCurvature(ulist(i),CtrlPoints,knots); % 离散曲率波动的地方的样条曲率值 end if num > 3 %% 二次查找,去除噪音点 tmpcurvlist = curvlist; tmpulist = ulist; tmpindex = index; index=[tmpindex(1)]; curvlist=[curvlist(1)]; ulist=0; for i=2:num-1 if tmpcurvlist(i)-tmpcurvlist(i-1)>1e-3 && tmpcurvlist(i)-tmpcurvlist(i+1)>1e-3 ulist=[ulist,tmpulist(i)]; curvlist=[curvlist,tmpcurvlist(i)]; index=[index;tmpindex(i)]; % continue; end % index(i)=[]; % ulist(i)=[]; % curvlist(i)=[]; end ulist=[ulist,1]; curvlist=[curvlist,tmpcurvlist(end)]; index=[index;tmpindex(end)]; end % figure; % plot(tobefit(:,1),tobefit(:,2),'r');hold on % plot(pos(:,1),pos(:,2),'k');hold on % grid on % for i=1:length(index) % plot(tobefit(index(i),1),tobefit(index(i),2),'b*');hold on % end end

destBlk=[];Vs=[0,0];Ve=[0,0]; startflag=0;endflag=0; [blockqueue] = GetQueue(blockInfo,0.3); k=length(blockqueue); for i=1:k blocklist=blockqueue(i).blocklist; if ~blockqueue(i).split %% line % 不用进行分割的线段直接赋值给控制点 tblk=blocklist(end,:); Vs = blockqueue(i).Ve; startflag=1; blk.type=tblk(1); if blk.type == 1 blk.ctrlpnt=[[tblk(2),tblk(3)];[tblk(4),tblk(5)]]; else blk.ctrlpnt=[[tblk(2),tblk(3)];[tblk(4),tblk(5)];[tblk(6),tblk(7)]]; end blk.knots=[]; blk.ids=[]; blk.us=[]; blk.ulist=[]; blk.curvlist=[]; destBlk=[destBlk;blk]; endflag = 0; % 终点向量 else if i~=k nextb=i+1; if ~blockqueue(nextb).split %% line % 下一段是直线,不需要进行拟合 Ve=blockqueue(nextb).Vs; Vs=blockqueue(i).Vs; endflag=1; end else Vs=blockqueue(i).Vs; Ve=blockqueue(i).Ve; % nextb=i+1; % if size(blockqueue) < nextb % 为空就需要用端点的切向量 % tblk=blocklist(end,:); % pe = [tblk(4), tblk(5), 0] - [tblk(6), tblk(7), 0]; % 起点 % ps = [tblk(2), tblk(3), 0] - [tblk(6), tblk(7), 0]; % 终点 % pe = pe / norm(pe); % ps = ps / norm(ps); % pn = cross(ps,pe); % 法向量 % % if tblk(8) < pi % Ve = cross(pn,pe); % 切向量 % else % Ve = -cross(pn,pe); % 切向量 % end % Ve = [Ve(1), Ve(2)]; % else % if ~blockqueue(nextb).split % 直线 % % else % % end % end end % if i == 1 % 第一段是圆弧 % tblk=blocklist(1,:); % pe = [tblk(4), tblk(5), 0] - [tblk(6), tblk(7), 0]; % 起点 % ps = [tblk(2), tblk(3), 0] - [tblk(6), tblk(7), 0]; % 终点 % pe = pe / norm(pe); % ps = ps / norm(ps); % pn = cross(ps,pe); % 法向量 % % if tblk(8) < pi % Vs = cross(pn,ps); % 切向量 % else % Vs = -cross(pn,ps); % 切向量 % end % Vs = [Vs(1), Vs(2)]; % end % blks = GetSplineBlk(blocklist,Vs,Ve,startflag,endflag);%%fit % 拟合 blks = GetSplineBlk_1(blocklist,Vs,Ve,startflag,endflag);%%fit % 拟合 destBlk=[destBlk;blks]; end end

1. 目标 计算器的实现目标是创建一个能够进行数学运算的程序,其主要目标包 括: 1. 支持基本数学运算:实现加法、减法、乘法和除法等基本算术运算。 2. 处理运算符优先级:正确处理不同运算符的优先级,确保表达式按照 数学规则进行计算。 3. 支持括号:能够处理带有括号的表达式,按照括号的优先级进行计算。 4. 处理多位数和小数:能够正确处理多位数和带小数点的数值,并进行 准确的运算。 5. 错误处理:能够检测并处理用户输入错误的情况,如非法字符、不完 整的表达式等,并给出相应的错误提示。 6. 提供用户界面:创建一个用户友好的界面,使用户能够输入表达式并 查看计算结果。 7. 可扩展性和可维护性:使用模块化的设计和合适的数据结构,使得代 码易于扩展和维护,可以方便地添加新的运算符或功能。 8. 良好的性能和效率:在处理大型表达式时,能够保持较高的计算性能 和效率,以便快速计算结果。 通过实现这些目标,计算器能够提供准确、可靠且易于使用的数学运算 功能,满足用户的计算需求,并能够适应不同的计算场景。 2. 模块划分 将计算器实现分解为多个模块可以提高代码的可维护性和可扩展性。以 下是一个可能的模块划分: 1. 用户界面模块: - 负责与用户进行交互,接收用户输入的数学表达式。 - 可以是一个命令行界面或图形用户界面(GUI)。 2. 表达式解析模块: - 将用户输入的数学表达式解析为中缀表达式。 - 可以实现中缀表达式的构建和验证。 3. 中缀转后缀模块: - 将中缀表达式转换为后缀表达式。 - 包括处理运算符优先级和括号匹配的逻辑。 4. 后缀表达式求值模块: - 根据后缀表达式计算表达式的值。 - 可以实现栈的操作和不同运算符的计算逻辑。 3 5. 错误处理模块: - 处理用户输入错误或计算过程中的错误情况。 - 包括错误提示和异常处理。 6. 输出模块: - 将计算结果输出给用户。 - 可以在用户界面模块中处理输出逻辑。 通过将计算器的功能划分为不同的模块,可以使代码更加清晰、模块化, 并且容易进行单元测试和扩展。每个模块都可以有自己的接口和实现,使得 团队成员可以独立地开发和维护各个模块。 3. 模块功能实现 3.1 表达式解析模块 要在 C 语言中实现计算器的表达式解析模块,可以按照以下步骤进行: 1. 定义所需的数据结构: - 创建一个结构体来表示表达式的每个元素,包括操作数和运算符。 - 可以使用链表或数组来存储表达式的元素。 2. 实现表达式解析函数: - 创建一个函数,接受表达式字符串作为输入,并返回解析后的表达式 数据结构。 - 遍历表达式字符串的每个字符: - 判断当前字符是数字还是运算符。 - 如果是数字,解析连续的字符,构造操作数,并将其添加到表达式 数据结构中。 - 如果是运算符,将其添加到表达式数据结构中。 - 返回解析后的表达式数据结构。c语言

大家在看

recommend-type

Xilinx ISE rs_decoder_ipcore and encoder License

Xilinx ISE RS编码解码IP核的License
recommend-type

毕业设计&课设-一个基于Matlab的PET仿真和重建框架,具有系统矩阵的分析建模,能够结合各种数据….zip

matlab算法,工具源码,适合毕业设计、课程设计作业,所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答! matlab算法,工具源码,适合毕业设计、课程设计作业,所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答! matlab算法,工具源码,适合毕业设计、课程设计作业,所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答! matlab算法,工具源码,适合毕业设计、课程设计作业,所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答! matlab算法,工具源码,适合毕业设计、课程设计作业,所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答! matlab算法,工具源码,适合毕业设计、课程设计作业,所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随
recommend-type

MATLAB机械臂简单控制仿真(Simulink篇-总).zip

MATLAB下机器人可视化与控制---simulink篇中的简单例子,在Simulink中做了预定义轨迹的运动和Slider Gain控制的运动,用GUI控制的关节代码在MATLAB下机器人可视化与控制
recommend-type

使用 GCC 构建 STM23F0 ARM 项目的模板源码

使用 GCC 构建 STM23F0 ARM 项目的模板源码,具体请看 README
recommend-type

详细说明 VC++的MFC开发串口调试助手源代码,包括数据发送,接收,显示制式等29782183com

详细说明 VC++的MFC开发串口调试助手源代码,包括数据发送,接收,显示制式等29782183com

最新推荐

recommend-type

计算机网络学习中学员常见问题与改进方法

计算机网络学习中学员常见问题与改进方法+
recommend-type

基于高斯混合模型(GMM)和主成分分析(PCA)的疲劳语音识别.zip

1.版本:matlab2014a/2019b/2024b 2.附赠案例数据可直接运行。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。
recommend-type

美国国际航空交通数据分析报告(1990-2020)

根据给定的信息,我们可以从中提取和分析以下知识点: 1. 数据集概述: 该数据集名为“U.S. International Air Traffic data(1990-2020)”,记录了美国与国际间航空客运和货运的详细统计信息。数据集涵盖的时间范围从1990年至2020年,这说明它包含了长达30年的时间序列数据,对于进行长期趋势分析非常有价值。 2. 数据来源及意义: 此数据来源于《美国国际航空客运和货运统计报告》,该报告是美国运输部(USDOT)所管理的T-100计划的一部分。T-100计划旨在收集和发布美国和国际航空公司在美国机场的出入境交通报告,这表明数据的权威性和可靠性较高,适用于政府、企业和学术研究等领域。 3. 数据内容及应用: 数据集包含两个主要的CSV文件,分别是“International_Report_Departures.csv”和“International_Report_Passengers.csv”。 a. International_Report_Departures.csv文件可能包含了以下内容: - 离港航班信息:记录了各航空公司的航班号、起飞和到达时间、起飞和到达机场的代码以及国际地区等信息。 - 航空公司信息:可能包括航空公司代码、名称以及所属国家等。 - 飞机机型信息:如飞机类型、座位容量等,这有助于分析不同机型的使用频率和趋势。 - 航线信息:包括航线的起始和目的国家及城市,对于研究航线网络和优化航班计划具有参考价值。 这些数据可以用于航空交通流量分析、机场运营效率评估、航空市场分析等。 b. International_Report_Passengers.csv文件可能包含了以下内容: - 航班乘客信息:可能包括乘客的国籍、年龄、性别等信息。 - 航班类型:如全客机、全货机或混合型航班,可以分析乘客运输和货物运输的比例。 - 乘客数量:记录了各航班或航线的乘客数量,对于分析航空市场容量和增长趋势很有帮助。 - 飞行里程信息:有助于了解国际间不同航线的长度和飞行距离,为票价设置和燃油成本分析提供数据支持。 这些数据可以用于航空客运市场分析、需求预测、收益管理等方面。 4. 数据分析和应用实例: - 航空流量分析:通过分析离港航班数据,可以观察到哪些航线最为繁忙,哪些机场的国际航空流量最大,这有助于航空公司调整航班时刻表和运力分配。 - 市场研究:乘客数据可以揭示不同国家和地区之间的人口流动趋势,帮助航空公司和政府机构了解国际旅行市场的需求变化。 - 飞机利用率:结合飞机机型和飞行频率信息,可以对特定机型的使用率进行分析,评估飞机维护需求和燃油效率。 - 安全监管:通过对比不同航空公司和航班的安全记录,监管机构可以更有效地评估航空公司的安全性能,并采取必要的监管措施。 5. 技术和方法论: 分析此类数据通常涉及数据清洗、数据整合、统计分析、时间序列分析、预测建模等数据科学方法。使用Excel、SQL、R、Python等工具进行数据处理和分析是常见的做法。例如,可以使用Python的Pandas库来清洗和准备数据,使用Matplotlib和Seaborn库来可视化数据,然后利用Scikit-learn或Statsmodels库来构建预测模型。 通过以上知识点的提取和分析,我们可以理解到“U.S. International Air Traffic data(1990-2020)-数据集”的重要性,它不仅记录了跨越30年的航空交通数据,还为各种分析和应用提供了详实的基础信息。对于航空业从业者、政策制定者、研究人员以及数据分析师来说,这是一个极具价值的数据资源。
recommend-type

统计学视角:深入理解最小二乘法的概率论基础

# 1. 最小二乘法的基本概念 最小二乘法(Least Squares Method, LSM)是统计学和数据分析中广泛使用的一种数学优化技术。其主要目的是通过最小化误差的平方和来寻找数据的最佳函数匹配。这种方法最早由高斯提出,但在工程、物理、经济和其他领域中有着广泛的应用。 在本章中,我们将首先了
recommend-type

vscode中使用Codeium

<think>好的,我需要回答用户如何在VSCode中使用Codeium插件的问题。首先,我需要回顾用户提供的引用内容,看看是否有相关信息。用户提供的引用[1]提到了Codeium Chat可以解释代码中的问题,引用[2]提到了在IDEA中的一些问题,可能对VSCode的安装有帮助。用户还提到了安装步骤、基本功能、常见问题等。 首先,我应该分步骤说明安装过程,包括在VSCode扩展商店搜索Codeium并安装。然后,登录部分可能需要用户访问仪表板获取API密钥,引用[2]中提到登录问题,可能需要提醒用户注意网络或权限设置。 接下来是基本功能,比如代码自动补全和Chat功能。引用[1]提到C
recommend-type

UniMoCo:统一框架下的多监督视觉学习方法

在详细解析“unimoco”这个概念之前,我们需要明确几个关键点。首先,“unimoco”代表的是一种视觉表示学习方法,它在机器学习尤其是深度学习领域中扮演着重要角色。其次,文章作者通过这篇论文介绍了UniMoCo的全称,即“Unsupervised, Semi-Supervised and Full-Supervised Visual Representation Learning”,其背后的含义是在于UniMoCo框架整合了无监督学习、半监督学习和全监督学习三种不同的学习策略。最后,该框架被官方用PyTorch库实现,并被提供给了研究者和开发者社区。 ### 1. 对比学习(Contrastive Learning) UniMoCo的概念根植于对比学习的思想,这是一种无监督学习的范式。对比学习的核心在于让模型学会区分不同的样本,通过将相似的样本拉近,将不相似的样本推远,从而学习到有效的数据表示。对比学习与传统的分类任务最大的不同在于不需要手动标注的标签来指导学习过程,取而代之的是从数据自身结构中挖掘信息。 ### 2. MoCo(Momentum Contrast) UniMoCo的实现基于MoCo框架,MoCo是一种基于队列(queue)的对比学习方法,它在训练过程中维持一个动态的队列,其中包含了成对的负样本。MoCo通过 Momentum Encoder(动量编码器)和一个队列来保持稳定和历史性的负样本信息,使得模型能够持续地进行对比学习,即使是在没有足够负样本的情况下。 ### 3. 无监督学习(Unsupervised Learning) 在无监督学习场景中,数据样本没有被标记任何类别或标签,算法需自行发现数据中的模式和结构。UniMoCo框架中,无监督学习的关键在于使用没有标签的数据进行训练,其目的是让模型学习到数据的基础特征表示,这对于那些标注资源稀缺的领域具有重要意义。 ### 4. 半监督学习(Semi-Supervised Learning) 半监督学习结合了无监督和有监督学习的优势,它使用少量的标注数据与大量的未标注数据进行训练。UniMoCo中实现半监督学习的方式,可能是通过将已标注的数据作为对比学习的一部分,以此来指导模型学习到更精准的特征表示。这对于那些拥有少量标注数据的场景尤为有用。 ### 5. 全监督学习(Full-Supervised Learning) 在全监督学习中,所有的训练样本都有相应的标签,这种学习方式的目的是让模型学习到映射关系,从输入到输出。在UniMoCo中,全监督学习用于训练阶段,让模型在有明确指示的学习目标下进行优化,学习到的任务相关的特征表示。这通常用于有充足标注数据的场景,比如图像分类任务。 ### 6. PyTorch PyTorch是一个开源机器学习库,由Facebook的人工智能研究团队开发,主要用于计算机视觉和自然语言处理等任务。它被广泛用于研究和生产环境,并且因其易用性、灵活性和动态计算图等特性受到研究人员的青睐。UniMoCo官方实现选择PyTorch作为开发平台,说明了其对科研社区的支持和对易于实现的重视。 ### 7. 可视化表示学习(Visual Representation Learning) 可视化表示学习的目的是从原始视觉数据中提取特征,并将它们转换为能够反映重要信息且更易于处理的形式。在UniMoCo中,无论是无监督、半监督还是全监督学习,最终的目标都是让模型学习到有效的视觉表示,这些表示可以用于下游任务,如图像分类、目标检测、图像分割等。 ### 8. 标签队列(Label Queue) UniMoCo通过标签队列维护受监管的标签,这可能意味着对于那些半监督或全监督学习的任务,模型在进行对比学习时,会参考这些来自标签队列的数据。标签队列机制能帮助模型更好地利用有限的标注数据,增强模型的泛化能力。 ### 结论 UniMoCo的提出,以及其官方PyTorch实现的发布,将对计算机视觉领域产生深远影响。它不仅提供了一个统一的对比学习框架,使得从无监督到全监督的学习过程更加灵活和高效,而且为研究者们提供了一个强力的工具,以便更好地探索和实现各种视觉任务。UniMoCo的研究和应用前景,为机器学习尤其是深度学习在视觉领域的研究和实践提供了新的视角和可能。
recommend-type

【MATLAB算法精讲】:最小二乘法的实现与案例深度分析

# 1. 最小二乘法的基本原理 最小二乘法是一种数学优化技术,它通过最小化误差的平方和来寻找数据的最佳函数匹配。其核心思想是选择一条曲线,使得所有观察点到这条曲线的距离之和最小。这种方法广泛应用于统计学、信号处理、工程学和经济学等领域,尤其适用于需要通过一组数据点来确定函数参数的情况。 ## 1.1 统计学视角下的最小二乘法 在统计学中,最小二乘法经常用于
recommend-type

Idea使用教程+jdk配置

<think>好的,我现在需要回答用户关于IntelliJ IDEA使用教程和JDK配置方法的问题。首先,用户明确提到了参考站内引用中的内容,引用[1]和引用[2]都涉及JDK的配置步骤,但看起来这些引用内容可能来自其他问题或文档,可能与当前问题不完全相关,但用户希望我利用这些信息来组织回答。 首先,我需要确认IntelliJ IDEA配置JDK的基本步骤,并整合用户提供的引用内容。引用[1]提到选择JDK安装根目录,例如D:\develop\Java\jdk-17,这说明配置时需要定位到JDK的主目录。引用[2]则提到了通过New按钮选择JDK版本,并完成项目创建,这部分可能涉及到项目设置
recommend-type

GitHub入门实践:审查拉取请求指南

从提供的文件信息中,我们可以抽取以下知识点: **GitHub入门与Pull Request(PR)的审查** **知识点1:GitHub简介** GitHub是一个基于Git的在线代码托管和版本控制平台,它允许开发者在互联网上进行代码的托管和协作。通过GitHub,用户可以跟踪和管理代码变更,参与开源项目,或者创建自己的私有仓库进行项目协作。GitHub为每个项目提供了问题跟踪和任务管理功能,支持Pull Request机制,以便用户之间可以进行代码的审查和讨论。 **知识点2:Pull Request的作用与审查** Pull Request(PR)是协作开发中的一个重要机制,它允许开发者向代码库贡献代码。当开发者在自己的分支上完成开发后,他们可以向主分支(或其他分支)提交一个PR,请求合入他们的更改。此时,其他开发者,包括项目的维护者,可以审查PR中的代码变更,进行讨论,并最终决定是否合并这些变更到目标分支。 **知识点3:审查Pull Request的步骤** 1. 访问GitHub仓库,并查看“Pull requests”标签下的PR列表。 2. 选择一个PR进行审查,点击进入查看详细内容。 3. 查看PR的标题、描述以及涉及的文件变更。 4. 浏览代码的具体差异,可以逐行审查,也可以查看代码变更的概览。 5. 在PR页面添加评论,可以针对整个PR,也可以针对特定的代码行或文件。 6. 当审查完成后,可以提交评论,或者批准、请求修改或关闭PR。 **知识点4:代码审查的最佳实践** 1. 确保PR的目标清晰且具有针对性,避免过于宽泛。 2. 在审查代码时,注意代码的质量、结构以及是否符合项目的编码规范。 3. 提供建设性的反馈,指出代码的优点和需要改进的地方。 4. 使用清晰、具体的语言,避免模糊和主观的评论。 5. 鼓励开发者间的协作,而不是单向的批评。 6. 经常审查PR,以避免延迟和工作积压。 **知识点5:HTML基础** HTML(HyperText Markup Language)是用于创建网页的标准标记语言。它通过各种标签(如`<p>`用于段落,`<img>`用于图片,`<a>`用于链接等)来定义网页的结构和内容。HTML文档由元素组成,这些元素通过开始标签和结束标签来标识。例如,`<p>This is a paragraph.</p>`。HTML的最新版本是HTML5,它引入了许多新的元素和API,增强了对多媒体、图形和本地存储的支持。 **知识点6:GitHub Pages功能介绍** GitHub Pages是一个静态站点托管服务,允许用户直接从GitHub仓库中发布个人、组织或项目的网站。你可以通过设置一个专门的分支来存放你的网站源代码,然后利用GitHub Pages的设置选项,选择分支并发布你的网站。发布的网站将可以通过一个自定义的URL访问,这个URL通常是`username.github.io/repo-name`的格式。这为开发者提供了一个简单而快速的方法来搭建个人或项目的展示页面。 **知识点7:简单的游戏开发实践** 文件描述中提到了一个基于项目的学习活动,通过游戏的形式,让入门人员体验操作和理解基本的游戏开发概念。在这个活动中,参与者通过键盘操作控制形状的旋转和移动,目标是创建无空隙的完整行,这涉及到游戏逻辑、用户输入处理和图形界面显示等基础知识。该活动可能使用了HTML、JavaScript和CSS等前端技术实现,参与者通过实践操作来学习如何编程,并理解基本的游戏设计原理。
recommend-type

【R语言高级教程】:最小二乘法从入门到精通

# 1. 最小二乘法的理论基础 最小二乘法是数学优化技术之一,广泛应用于统计学、数据分析和工程学等领域。其核心思想在于找到一条直线(或曲线),使得所有观测点到该直线的垂直距离之和最小,即误差平方和最小。这一方法不仅简单易行,而且可以有效减少异常值对模型的影响,使得参数估计更加稳定。 ## 1.1 最小二乘法的数学表述 在最基本的线性回归模型中,最小二乘法通过最小化误差的平方和来寻找最