移动通信中的算法问题 实验一 计算信号的强度

感谢学长在他的博客无私分享的高质量代码,才让我能够顺利地完成这次实验
在此融入些鄙人粗浅的理解分享出来供更多人学习

一. 引言

  1. 移动通信中的数字信号往往是复数信号a+bi,储存时分开储存复数的实部和虚部a、b也称Q(quotient)、I(imaginary number)。

  2. 终端在每个地点收到的是多个基站信号的叠加,需要依据强度,判断选择接入哪个基站。而这种判断是随着终端位置的改变需要不断进行的。

  3. 信号强度的计算(N为数据组数):
    在这里插入图片描述

  4. 信号强度的排序:可以采用冒泡排序、插入排序、希尔排序等方法。

  5. 当基站信号均较弱时,信号强度排序可能会在几个网络之间不断跳动,故加上门限的限定能够避免网络在多个基站间反复切换。

二. 系统设计要求

总体要求:计算12个候选小区的强度,找出大于强度门限的小区,并进行从强到弱的排序。强度门限自行设定。

  1. 输出中间过程的信息。
  2. 打印各小区强度以及小区排序的结果(小区ID即文件名)。
  3. 打印设置的强度门限。

三. 设计思路与方案

1. 流程图

在这里插入图片描述

2.全局变量及结构体

#define NUM 12//数据组数
#define MAX 30000 //data中存放信号强度的实部和虚部Q和I共30000个数据

struct Area//小区结构体
{
    char ID[15];//小区名称——文件名称
    double avg_strength;//小区信号平均强度
};
struct Area area[NUM];//小区结构体数组

3.算法设计

整体代码
#include <stdio.h>
#include <string.h>
#include <math.h>

#define NUM 12//数据组数
#define MAX 30000 //data中存放信号强度的实部和虚部Q和I共30000个数据

struct Area//小区结构体
{
    char ID[15];//小区名称——文件名称
    double avg_strength;//小区信号平均强度
};
struct Area area[NUM];//小区结构体数组

void ID_init()//初始化小区名称
{
    strcpy(area[0].ID,"data24.txt");
    strcpy(area[1].ID,"data25.txt");
    strcpy(area[2].ID,"data26.txt");
    strcpy(area[3].ID,"data27.txt");
    strcpy(area[4].ID,"data28.txt");
    strcpy(area[5].ID,"data29.txt");
    strcpy(area[6].ID,"data30.txt");
    strcpy(area[7].ID,"data31.txt");
    strcpy(area[8].ID,"data32.txt");
    strcpy(area[9].ID,"data33.txt");
    strcpy(area[10].ID,"data34.txt");
    strcpy(area[11].ID,"data35.txt");
}
int calculate(struct Area *area,double Q,double I)//求平均强度函数
{
	static double sum; //利用static对数据进行累加
	static int i = 0; //利用static对计算次数进行统计
	sum = sum + sqrt(Q * Q + I * I); //信号强度计算公式并对结果求和
	i++;//计算次数累加
	if (i == MAX/2)//当执行到MAX/2次时执行以下代码
	{
		area->avg_strength = sum / (MAX/2);//求平均信号强度并写入结构体
		sum = 0;//总和清零
		i = 0;//次数清零
		return 0;//返回0表示计算完成
	}
	return 1;//返回1表示计算未完成
}
void fileop(int num)//读取文件
{
    FILE* fp;
    int flag;//设置旗标flag用于检测calculate()的返回值,从而判断是否计算完所有数据
    double Q,I;//定义双精度浮点数存放信号强度的实部和虚部
    if((fp = fopen(area[num].ID,"r")) == NULL)
    {
        printf("打开文件错误");
    }
    else
    {
        for(int i=0;i<MAX/2;i++)//边读取文件边进行计算
        {
            fscanf(fp,"%lf %lf",&Q,&I);//读取文件,并将数值存储到Q和I中
            calculate(&area[num],Q,I);
            flag = calculate(&area[num],Q,I);
            if(flag == 0)
            {
                fclose(fp);
                break;
            }
        }
    }
}

void sort()//冒泡算法排序
{
	struct Area temp;
	for (int i=0; i<=NUM-1; i++)
	{
		for (int j=0; j<=NUM-1-i; j++)
		{
			if (area[j].avg_strength < area[j+1].avg_strength)
			{
				temp = area[j] ;
				area[j] = area[j+1];
				area[j+1] = temp;
			}
		}
	}
}
int main()
{
    double threshold;//定义强度门限
    ID_init();//初始化小区名称
    for(int i=0; i<NUM; i++)
    {
        fileop(i);
        printf("小区%s信号平均强度为:%lf\n",area[i].ID,area[i].avg_strength);
    }
    sort();
    printf("\n排序结果为:\n");
    for(int i=0; i<NUM; i++)
    {
        fileop(i);
        printf("小区%s信号平均强度为:%lf\n",area[i].ID,area[i].avg_strength);
    }
    printf("请输入强度门限:\n");
    scanf("%lf",&threshold);
    printf("\n满足门限条件的小区:\n");
    for (int i = 0; i < NUM; i++)
	{
		if(area[i].avg_strength>=threshold)//如果满足门限条件打印相关信息
			printf("ID:%s \t信号平均强度:%lf\n", area[i].ID, area[i].avg_strength);
	}
}

3.1初始化小区名称
void ID_init()//初始化小区名称
{
    strcpy(area[0].ID,"data24.txt");
    strcpy(area[1].ID,"data25.txt");
    strcpy(area[2].ID,"data26.txt");
    strcpy(area[3].ID,"data27.txt");
    strcpy(area[4].ID,"data28.txt");
    strcpy(area[5].ID,"data29.txt");
    strcpy(area[6].ID,"data30.txt");
    strcpy(area[7].ID,"data31.txt");
    strcpy(area[8].ID,"data32.txt");
    strcpy(area[9].ID,"data33.txt");
    strcpy(area[10].ID,"data34.txt");
    strcpy(area[11].ID,"data35.txt");
}
3.2 平均强度计算
int calculate(struct Area *area,double Q,double I)//求平均强度函数
{
	static double sum; //利用static对数据进行累加
	static int i = 0; //利用static对计算次数进行统计
	sum = sum + sqrt(Q * Q + I * I); //信号强度计算公式并对结果求和
	i++;//计算次数累加
	if (i == MAX/2)//当执行到MAX/2次时执行以下代码
	{
		area->avg_strength = sum / (MAX/2);//求平均信号强度并写入结构体
		sum = 0;//总和清零
		i = 0;//次数清零
		return 0;//返回0表示计算完成
	}
	return 1;//返回1表示计算未完成
}

在这里插入图片描述

3.3读文件传递参数
void fileop(int num)//读取文件
{
    FILE* fp;
    int flag;//设置旗标flag用于检测calculate()的返回值,从而判断是否计算完所有数据
    double Q,I;//定义双精度浮点数存放信号强度的实部和虚部
    if((fp = fopen(area[num].ID,"r")) == NULL)
    {
        printf("打开文件错误");
    }
    else
    {
        for(int i=0;i<MAX/2;i++)//边读取文件边进行计算
        {
            fscanf(fp,"%lf %lf",&Q,&I);//读取文件,并将数值存储到Q和I中
            calculate(&area[num],Q,I);
            flag = calculate(&area[num],Q,I);
            if(flag == 0)
            {
                fclose(fp);
                break;
            }
        }
    }
}

在这里插入图片描述

3.4冒泡排序
void sort()//冒泡算法排序
{
	struct Area temp;
	for (int i=0; i<=NUM-1; i++)
	{
		for (int j=0; j<=NUM-1-i; j++)
		{
			if (area[j].avg_strength < area[j+1].avg_strength)
			{
				temp = area[j] ;
				area[j] = area[j+1];
				area[j+1] = temp;
			}
		}
	}
}
3.5主函数
int main()
{
    double threshold;//定义强度门限
    ID_init();//初始化小区名称
    for(int i=0; i<NUM; i++)
    {
        fileop(i);
        printf("ID:%s信号平均强度为:%lf\n",area[i].ID,area[i].avg_strength);
    }
    sort();
    printf("\n排序结果为:\n");
    for(int i=0; i<NUM; i++)
    {
        fileop(i);
        printf("ID;%s信号平均强度为:%lf\n",area[i].ID,area[i].avg_strength);
    }
    printf("\n请输入强度门限:\n");
    scanf("%lf",&threshold);
    printf("\n满足门限条件的小区有:\n");
    for (int i = 0; i < NUM; i++)
	{
		if(area[i].avg_strength>=threshold)//如果满足门限条件打印相关信息
			printf("ID:%s \t信号平均强度:%lf\n", area[i].ID, area[i].avg_strength);
	}
    if(area[0].avg_strength<threshold)
        printf("没有满足门限条件的小区");
}

四. 调试

在这里插入图片描述
在这里插入图片描述

对比单精度和双精度浮点数存放数据,单精度浮点数在小数点后六位便会存在误差,而双精度浮点型存储的数到小数点后16位才会出现误差,故采用双精度浮点型存储数据所得的精度比单精度浮点型高12个数量级。

本次代码的实现难点在于,读文件以及数据计算的操作。遇到的第一个问题:如何确保从单个文件中30000个数据按照Q和I的顺序读取并存储到程序中。倘若使用数组将Q和I分别存储,那么还需要一个循环语句对它们进行求和,故采用一边读取一边传递参数给计算函数,可以很大程度上简化代码量。第二个问题是:12个小区对应了12组文件一个一个打开无疑使代码显得十分冗长。故采用结构体分别存放这12组文件的ID和平均强度,用for循环对结构体进行操作。

五.心得体会

在实际工程中C语言的基本操作——如指针,结构体,文件的运用是必须掌握的,我的基础尚且薄弱仍需进一步学习。

六.意见

七.附录

结果展示

在这里插入图片描述
这里是一些写报告时可以用到的网站
流程图绘制:https://app.diagrams.net/?libs=general;flowchart
C代码美化:https://highlightcode.com/

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值