使用 ref 和 out 传递数组

xiaoxiao2021-02-28  78

使用 ref 和 out 传递数组

在项目中利用到了自己封装的一个FFT算法,这个算法需要返回两个数组值,因此考虑到了使用ref和out来传递数组。

1.ref和out的区别

数组类型的 ref 参数必须由调用方明确赋值(传入的参数必须先被初始化)。 因此,不需要由被调用方明确赋值。 可以将数组类型的 ref 参数更改为调用的结果。 例如,可以为数组赋以 null 值,或将其初始化为另一个数组。在使用数组类型的 out 参数前必须先为其赋值;即必须由被调用方(必须在方法中对其完成初始化)为其赋值。out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候。

2.实例

傅里叶变换的方法,返回两个数组,幅值和频率 //1.使用out参数

public void TTFTrans(out double[] range_data, out double[] frequency_data) { //**必须在方法中对其完成初始化** range_data = new double[512]; frequency_data = new double[512]; double fs = 50; Complex[] real_data = new Complex[1024]; Random r = new Random(); //采样1024个数据 for (int i = 0; i < 1024; i++) { real_data[i] = 15 * Math.Sin(Math.PI * 2 * 1 * (i / fs)) + 10 * Math.Sin(Math.PI * 2 * 5 * (i / fs)) + 5 * Math.Sin(Math.PI * 2 * 10 * (i / fs)) + r.Next(0, 20) * Math.Sin(Math.PI * 2 * r.Next(0, 10) * 20 * ((i) / fs)); } Complex[] com = FFTT.fft_frequency(real_data); //计算所得到幅度值 //对采样数组进行傅里叶变换 double N = com.Length; for (int i = 0; i < com.Length / 2; i++) { double rr = (com[i].Real); double ri = (com[i].Imaginary); frequency_data[i] = i * (fs / N); range_data[i] = (Math.Sqrt((rr * rr) + (ri * ri))) / (N / 2); } }

FFTT.cs:

public static class FFTT { public static Complex[] fft_frequency(Complex[] sourceData) { int countN = sourceData.Length; //2的r次幂为N,求出r.r能代表fft算法的迭代次数 int r = Convert.ToInt32(Math.Log(countN, 2)); //分别存储蝶形运算过程中左右两列的结果 Complex[] interVar1 = new Complex[countN]; Complex[] interVar2 = new Complex[countN]; interVar1 = (Complex[])sourceData.Clone(); //w代表旋转因子 Complex[] w = new Complex[countN / 2]; //为旋转因子赋值。(在蝶形运算中使用的旋转因子是已经确定的,提前求出以便调用) //旋转因子公式 \ /\ /k __ // \/ \/N -- exp(-j*2πk/N) //这里还用到了欧拉公式 for (int i = 0; i < countN / 2; i++) { double angle = -i * Math.PI * 2 / countN; w[i] = new Complex(Math.Cos(angle), Math.Sin(angle)); } //蝶形运算 for (int i = 0; i < r; i++) { //i代表当前的迭代次数,r代表总共的迭代次数. //i记录着迭代的重要信息.通过i可以算出当前迭代共有几个分组,每个分组的长度 //interval记录当前有几个组 // <<是左移操作符,左移一位相当于*2 //多使用位运算符可以人为提高算法速率^_^ int interval = 1 << i; //halfN记录当前循环每个组的长度N int halfN = 1 << (r - i); //循环,依次对每个组进行蝶形运算 for (int j = 0; j < interval; j++) { //j代表第j个组 //gap=j*每组长度,代表着当前第j组的首元素的下标索引 int gap = j * halfN; //进行蝶形运算 for (int k = 0; k < halfN / 2; k++) { interVar2[k + gap] = interVar1[k + gap] + interVar1[k + gap + halfN / 2]; interVar2[k + halfN / 2 + gap] = (interVar1[k + gap] - interVar1[k + gap + halfN / 2]) * w[k * interval]; } } //将结果拷贝到输入端,为下次迭代做好准备 interVar1 = (Complex[])interVar2.Clone(); } //将输出码位倒置 for (uint j = 0; j < countN; j++) { //j代表自然顺序的数组元素的下标索引 //用rev记录j码位倒置后的结果 uint rev = 0; //num作为中间变量 uint num = j; //码位倒置(通过将j的最右端一位最先放入rev右端,然后左移,然后将j的次右端一位放入rev右端,然后左移...) //由于2的r次幂=N,所以任何j可由r位二进制数组表示,循环r次即可 for (int i = 0; i < r; i++) { rev <<= 1; rev |= num & 1; num >>= 1; } interVar2[rev] = interVar1[j]; } return interVar2; } }

客户端调用:

public MainWindow() { InitializeComponent(); ////声明double类型数组,用来接收傅里叶变换返回的幅值 double[] range_data = null;//幅值 //声明double类型数组,用来接收傅里叶变换返回的频率 double[] frequency_data = null;//频率 //**传入参数不需要初始化** TTFTrans(out range_data, out frequency_data); for (int i = 0; i < range_data.Length; i++) { Console.WriteLine(range_data[i].ToString()); } }

//2.使用ref参数

public void TTFTrans(ref double[] range_data,ref double[] frequency_data) { double fs = 50; Complex[] real_data = new Complex[1024]; Random r = new Random(); //采样1024个点 for (int i = 0; i < 1024; i++) { real_data[i] = 15 * Math.Sin(Math.PI * 2 * 1 * (i / fs)) + 10 * Math.Sin(Math.PI * 2 * 5 * (i / fs)) + 5 * Math.Sin(Math.PI * 2 * 10 * (i / fs)) + r.Next(0, 20) * Math.Sin(Math.PI * 2 * r.Next(0, 10) * 20 * ((i) / fs)); } Complex[] com = FFTT.fft_frequency(real_data); //计算所得到幅度值 //对采样数组进行傅里叶变换 double N = com.Length; for (int i = 0; i < com.Length / 2; i++) { double rr = (com[i].Real); double ri = (com[i].Imaginary); frequency_data[i] = i * (fs / N); range_data[i] = (Math.Sqrt((rr * rr) + (ri * ri))) / (N / 2); } }

客户端:

public MainWindow() { InitializeComponent(); //**使用ref传入的参数必须初始化** double[] range_data = new double[1024 / 2];//幅值 double[] frequency_data = new double[1024/2];//频率 TTFTrans( ref range_data,ref frequency_data); for (int i = 0; i < range_data.Length; i++) { Console.WriteLine(range_data[i].ToString()); } }

ref是有进有出,而out是只出不进

转载请注明原文地址: https://www.6miu.com/read-54864.html

最新回复(0)