搜索
bottom↓
回复: 103

C中怎么快速高效的把数组中的21个元素向后移动一位,队?

[复制链接]

出0入0汤圆

发表于 2014-3-19 08:59:32 | 显示全部楼层 |阅读模式
本帖最后由 guxingganyue 于 2014-3-19 15:33 编辑

如题,在C中定义了一个数组buffer0[21];AD后的数据每次都放到buffer0[20]中,即最后一个位置,在放之前,buffer0数组要整体向后移动一位,即按照如下的方式移动后再把新的AD数据放到buffer0[20]中

  1.       
  2. buffer0[0]=buffer0[1];
  3. buffer0[1]=buffer0[2];
  4. buffer0[2]=buffer0[3];
  5. buffer0[3]=buffer0[4];
  6. buffer0[4]=buffer0[5];
  7. buffer0[5]=buffer0[6];
  8. buffer0[6]=buffer0[7];
  9. buffer0[7]=buffer0[8];
  10. buffer0[8]=buffer0[9];
  11. buffer0[9]=buffer0[10];
  12. buffer0[10]=buffer0[11];
  13. buffer0[11]=buffer0[12];
  14. buffer0[12]=buffer0[13];
  15. buffer0[13]=buffer0[14];
  16. buffer0[14]=buffer0[15];
  17. buffer0[15]=buffer0[16];
  18. buffer0[16]=buffer0[17];
  19. buffer0[17]=buffer0[18];
  20. buffer0[18]=buffer0[19];
  21. buffer0[19]=buffer0[20];

  22. buffer0[20]=AD;
复制代码


移动完后再做一次极小值判断,判断如下:

  1. if((buffer0[10]<=buffer0[0])
  2. &&(buffer0[10]<=buffer0[1])
  3. &&(buffer0[10]<buffer0[2])
  4. &&(buffer0[10]<buffer0[3])
  5. &&(buffer0[10]<buffer0[4])
  6. &&(buffer0[10]<buffer0[5])
  7. &&(buffer0[10]<buffer0[6])
  8. &&(buffer0[10]<buffer0[7])
  9. &&(buffer0[10]<buffer0[8])
  10. &&(buffer0[10]<buffer0[9])//判断左边

  11. &&(buffer0[10]<buffer0[11])//判断右边
  12. &&(buffer0[10]<buffer0[12])
  13. &&(buffer0[10]<buffer0[13])
  14. &&(buffer0[10]<buffer0[14])
  15. &&(buffer0[10]<buffer0[15])
  16. &&(buffer0[10]<buffer0[16])
  17. &&(buffer0[10]<buffer0[17])
  18. &&(buffer0[10]<buffer0[18])
  19. &&(buffer0[10]<=buffer0[19])
  20. &&(buffer0[10]<=buffer0[20]))
  21. {
  22.     ;//处理
  23. }
复制代码



每得到一个AD数据,上面就得移动一次,比较判断一次。


上面的移动方法比用for循环移动高效,快速。哪位有什么好的方法比上面的方法还要高效,快速呢?(注:根据网友的建议用环形队列可以)

但是用环形队列后,我下面的if判断就又麻烦了,综合起来环形队列还是不能解决我的问题。还请高人指点。

54 63楼我把问题用举例的方式又描述了一次,请大家看完此楼后再看其他层哦

编译原因:把问题描述的更加清楚了。
再次编译原因:说明了有AD值后每次都要移动,比较一次。

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2014-3-19 09:16:07 | 显示全部楼层
>> 有什么好的方法比上面的方法还要高效,快速呢?

使用环状数组。

出0入0汤圆

发表于 2014-3-19 09:20:12 | 显示全部楼层
你想要做滑动平均吧,

定义一个全局变量index,
每次AD数值都存到 index所指示的buffer中,
index 自增,  index 从0 到 20 循环,

这样你就少去了for循环计算的步骤,节省了运行时间。

出0入0汤圆

发表于 2014-3-19 08:59:33 | 显示全部楼层
xiaomu 发表于 2014-3-19 09:20
你想要做滑动平均吧,

定义一个全局变量index,

哥们这叫移动一个字节……目前没见过什么好的方法

出0入0汤圆

发表于 2014-3-19 09:25:44 来自手机 | 显示全部楼层
改成环形队列可以快一些

出0入0汤圆

 楼主| 发表于 2014-3-19 09:27:34 | 显示全部楼层
rantingting 发表于 2014-3-19 09:23
哥们这叫移动一个字节……目前没见过什么好的方法

嗯,对,现在只要把所有字节都向后移动一位,至于处理那就是后面的事了

出0入0汤圆

发表于 2014-3-19 09:27:48 | 显示全部楼层
如果RAM够大,就定义个比较大的数组如: Buf[100],还有一个指针*buffer及指针偏移PBuf

unsigned char Buf[100];
unsigned char *buffer;
unsigned int PBuf;

PBuf = 0;
buffer = &(Buf[PBuf]);

以后每次用的时候PBUf++就可以了
PBuf = 80后,整天搬移到前端,重新开始

出0入0汤圆

发表于 2014-3-19 09:28:06 | 显示全部楼层
单靠软件的话没有比这更好了,除非有专门的硬件,如DMA之类的不用CPU处理。

出0入0汤圆

 楼主| 发表于 2014-3-19 09:29:08 | 显示全部楼层
sunnyqd 发表于 2014-3-19 09:25
改成环形队列可以快一些

要高效,快速

现在这样做只有20次的赋值语句,环形队列移动的话可以少于20次?

前提是每次新的数据都放在下标20中

出0入0汤圆

发表于 2014-3-19 09:30:33 | 显示全部楼层
定义个数组如: Buf[20],还有一个指针*buffer及指针偏移PBuf

PBuf = (PBuf +1)%20;

出0入0汤圆

 楼主| 发表于 2014-3-19 09:33:56 | 显示全部楼层
xiaomu 发表于 2014-3-19 09:20
你想要做滑动平均吧,

定义一个全局变量index,

不做滑动平均,就是把所有元素都向后移动一次,然后用中间的元素---下表为10,做一次判断即可

出0入0汤圆

 楼主| 发表于 2014-3-19 09:34:52 | 显示全部楼层
LiuCH 发表于 2014-3-19 09:30
定义个数组如: Buf[20],还有一个指针*buffer及指针偏移PBuf

PBuf = (PBuf +1)%20;

这个我把所有元素移动一次需要执行多少次呢?

出0入0汤圆

发表于 2014-3-19 09:36:36 | 显示全部楼层
为什么一定要把每次数据放在下标20???有什么特殊应用?  新加一个索引不行么,环形填入

出0入93汤圆

发表于 2014-3-19 09:38:10 | 显示全部楼层
guxingganyue 发表于 2014-3-19 09:33
不做滑动平均,就是把所有元素都向后移动一次,然后用中间的元素---下表为10,做一次判断即可 ...

1、环形队列是最高效的,只需要进行一次赋值,无需移动。
2、你的前提一定是要放到下标20,这个真心扯淡。
3、你只需要最中间的那个值,用环形队列一样可以啊,有什么问题?

出0入0汤圆

 楼主| 发表于 2014-3-19 09:41:11 | 显示全部楼层
huangqi412 发表于 2014-3-19 09:36
为什么一定要把每次数据放在下标20???有什么特殊应用?  新加一个索引不行么,环形填入 ...

嗯,放20的原因是用10那个元素来判断一下,就是中间的那个元素,如果能找到中间的那个元素的话,不一定要放到20那里

出0入0汤圆

 楼主| 发表于 2014-3-19 09:43:10 | 显示全部楼层
takashiki 发表于 2014-3-19 09:38
1、环形队列是最高效的,只需要进行一次赋值,无需移动。
2、你的前提一定是要放到下标20,这个真心扯淡 ...

你说的很对,我把最后一个数据放到20的原因就是中这21个元素中的中间元素来做一次判断

如果用环形队列可以解决中间数据问题的话就可以用环形队列

出0入0汤圆

 楼主| 发表于 2014-3-19 09:49:07 | 显示全部楼层
takashiki 发表于 2014-3-19 09:38
1、环形队列是最高效的,只需要进行一次赋值,无需移动。
2、你的前提一定是要放到下标20,这个真心扯淡 ...

忘了说下面的判断了。


下面的判断直接用10号元素和左右各10点比较大小来判断10号元素是否是一个极值。


如果用环形队列的话,下面我的这个判断是不是也要跟着变化呢???

出0入0汤圆

发表于 2014-3-19 09:50:41 | 显示全部楼层
guxingganyue 发表于 2014-3-19 09:41
嗯,放20的原因是用10那个元素来判断一下,就是中间的那个元素,如果能找到中间的那个元素的话,不一定要 ...

擦,为什么不能?  索引向前追10不就是了?
真不理解你怎么就这么一根筋扭着。

出0入0汤圆

发表于 2014-3-19 09:51:59 | 显示全部楼层
下标常量改变量,绝对位置改相对位置而已。

出0入0汤圆

发表于 2014-3-19 09:54:04 | 显示全部楼层
guxingganyue 发表于 2014-3-19 09:33
不做滑动平均,就是把所有元素都向后移动一次,然后用中间的元素---下表为10,做一次判断即可 ...

如果只是取得中间值做判断,那就简单多了

使用环形队列赋值, 0-20 循环, 记录最新数值的index,

使用计算公式  x = (index+11)%21;
buffer0[x] 就是你需要的中间值!

出0入0汤圆

发表于 2014-3-19 10:02:41 | 显示全部楼层
要照你这个编程思路,C语言没法用了,你自己挨个给变量分配地址吧,你应该全部搞清所有变量存放的绝对地址才能用嘛。

出0入0汤圆

 楼主| 发表于 2014-3-19 10:04:05 | 显示全部楼层
huangqi412 发表于 2014-3-19 09:51
下标常量改变量,绝对位置改相对位置而已。

忘了说下面的判断了。


下面的判断直接用10号元素和左右各10点比较大小来判断10号元素是否是一个极值。


如果用环形队列的话,下面我的这个判断是不是也要跟着变化呢???

出0入0汤圆

发表于 2014-3-19 10:10:56 | 显示全部楼层
就一个数字常量改变量你有多纠结啊。。。   死守着绝对尺度,很多问题是无解的,相对。。。

出0入0汤圆

发表于 2014-3-19 10:18:46 | 显示全部楼层
LS各位说的很清楚了,这种解决方法是最优的.

出0入0汤圆

 楼主| 发表于 2014-3-19 10:21:29 | 显示全部楼层
huangqi412 发表于 2014-3-19 10:10
就一个数字常量改变量你有多纠结啊。。。   死守着绝对尺度,很多问题是无解的,相对。。。 ...

问题描述已经更新到楼主位了,您看看看。

出0入0汤圆

 楼主| 发表于 2014-3-19 10:22:19 | 显示全部楼层
error_dan 发表于 2014-3-19 10:18
LS各位说的很清楚了,这种解决方法是最优的.

可能我没有说清楚,现在已经更新了问题描述,好像环形队列也不是很好

出0入0汤圆

发表于 2014-3-19 10:39:43 | 显示全部楼层
环形队列,不解释,还有,你没有必要每次都判断吧?每次添加哪个就判断哪个,如果当前添加的这个不满足条件,那么再连续20个你都不用判断了。算法问题。

出0入0汤圆

发表于 2014-3-19 10:59:18 | 显示全部楼层
編譯型語言沒有效率(執行效率),衹有編寫效率。
決定執行效率的,是編譯器。
如果你嫌C語言編譯器不夠好,你自己看着C語言原文,寫出功能一樣的彙編語言,然後再翻譯爲機器碼,這樣亦算完成了一次編譯(人腦編譯器)。這一段機器碼,可能比電腦生成的快,亦可能會更慢,但不太可能會相等。
這足以說明C語言本身,是和程序運行快慢無關的。
當然,寫出

  1. int i = 0;
  2. i += 1;
  3. i += 2;
  4. i += 3;
  5. i += 4;
  6. printf("哦,原來1+2+3+4=%u。", i);
复制代码

這樣的代碼來求1+2+3+4等於多少除外。


話說回來,你而今碰到的,是程序執行太慢的問題。根據我前面講的,無論你的C語言怎樣寫,衹要是正常人寫出的代碼,編譯器都會盡它所能,幫你生成最快的機器碼。所以,你的着手點,不是C語言代碼本身,而是你的思想,你的策略,你的算法。
冒昧打箇比方,你的代碼就好比前述求1+2+3+4的代碼。你要做的,不是考慮這裏加箇循環,哪裏減箇變量,而是換成下面的代碼。

  1. int i = 0;
  2. i = 1 + 2 + 3 + 4;
  3. printf("哦,原來1+2+3+4=%u。", i);
复制代码

看,這是和語言本身無關的。

出0入169汤圆

发表于 2014-3-19 11:19:50 | 显示全部楼层
LZ是一根筋,用循环队列就行了。找极小值也不是问题,可以用索引算。

出0入0汤圆

发表于 2014-3-19 11:51:56 | 显示全部楼层
楼上的已经把问题解决了,楼主多想想

出0入0汤圆

 楼主| 发表于 2014-3-19 12:28:11 | 显示全部楼层
鼻儿眼睛花 发表于 2014-3-19 10:39
环形队列,不解释,还有,你没有必要每次都判断吧?每次添加哪个就判断哪个,如果当前添加的这个不满足条件 ...

每读取到一个AD值后就得判断一次

出0入0汤圆

发表于 2014-3-19 12:38:40 | 显示全部楼层
不想说啥了。。。

出0入0汤圆

 楼主| 发表于 2014-3-19 12:44:32 | 显示全部楼层
qlb1234 发表于 2014-3-19 10:59
編譯型語言沒有效率(執行效率),衹有編寫效率。
決定執行效率的,是編譯器。
如果你嫌C語言編譯器不夠好 ...

道理却是是这么讲的。

出0入0汤圆

发表于 2014-3-19 12:47:50 | 显示全部楼层
花了点时间写了个循环队列, LZ看来只能做伸手党了

#include "LIMITS.H"
#include "stdlib.h"
#include "stdio.h"

#ifndef ARRAY_COUNT
#define ARRAY_COUNT(a)   (sizeof(a)/sizeof(a[0]))
#endif

static int index = 0;       //循环列队写入位置
static int buffer_count = 0;//循环列队里有效数据个数
static long buffer_sum = 0; //循环列队累加和
static int buffer[21];

int buffer_min(void)
{
    int min = INT_MAX;
    int n = buffer_count;
    while(n-- > 0)
    {
        if(min > buffer[n] )
        {
            min = buffer[n];
        }
    }
    return min;
}

int buffer_max(void)
{
    int max = INT_MIN;
    int n = buffer_count;
    while(n-- > 0)
    {
        if(max < buffer[n] )
        {
            max = buffer[n];
        }
    }
    return max;
}


void buffer_add(int new_num)
{
    if( buffer_count<ARRAY_COUNT(buffer) )
    {
        buffer_count++;
    }
    else
    {
        buffer_sum -= buffer[index];
    }
    buffer[index] = new_num;
    buffer_sum += new_num;
    if( ++index>=ARRAY_COUNT(buffer) )
    {
        index = 0;
    }
}

void test(void)
{
    volatile int i, min, max, count;
    volatile long sum;
    for(i=0; i<10; i++)
    {
        buffer_add(i);
    }
    min = buffer_min();
    max = buffer_max();
    sum = buffer_sum;
    count = buffer_count;
    //printf("min=%d, max=%d, sum=%d, count=%d\n", min, max, sum, count);
    //
    for(i=10; i<40; i++)
    {
        buffer_add(i);
    }
    min = buffer_min();
    max = buffer_max();
    sum = buffer_sum;
    sum = buffer_sum;
    count = buffer_count;
    //printf("min=%d, max=%d, sum=%d, count=%d\n", min, max, sum, count);
}

出0入0汤圆

发表于 2014-3-19 12:50:37 | 显示全部楼层
不要移动数据……定义一个pos来指示当前写入位置就可以了
buffer[pos++] = newADC;
if(pos>=sizeof(buffer))
{
      pos = 0;
}

出0入0汤圆

发表于 2014-3-19 13:24:21 | 显示全部楼层
哎,看了半天,楼主好象没明白啊? 真让人捉急啊!
楼主就是卡这了,一时半会没转过来,他想想就好了,转过来了,一目了然!

出0入0汤圆

发表于 2014-3-19 13:38:07 | 显示全部楼层
我发了源码, LZ就跑了? 不打算给分了?

出0入0汤圆

发表于 2014-3-19 13:45:50 | 显示全部楼层
snoopyzz 发表于 2014-3-19 13:38
我发了源码, LZ就跑了? 不打算给分了?

无用功而已。
LZ是要在采样序列里出现极小值的时候,执行相应的处理代码。
LZ规定的极小值的判断条件是:(1)比前8个采样值小;(2)比后8个采样值小;(3)不比前第9、10个采样值大;(4)不比后第9、10个采样值大。

我看除了LZ位代码,没有更优化的方法可以实现等价的功能了。

出0入42汤圆

发表于 2014-3-19 14:07:17 | 显示全部楼层
1:好好说下那个极值最终怎么计算的, 其它的慢慢说.
2:加当前位置直接用数组循环比较简单---这就是个环形队列.  完全可以应付前后几个之间的查询.
3:lz你还是改行吧, 别碰代码了,不适合你.

出0入0汤圆

发表于 2014-3-19 14:29:45 | 显示全部楼层
本帖最后由 鼻儿眼睛花 于 2014-3-19 14:33 编辑
mitchell 发表于 2014-3-19 13:45
无用功而已。
LZ是要在采样序列里出现极小值的时候,执行相应的处理代码。
LZ规定的极小值的判断条件是: ...


太多重复判断了,根本没有必要,比如,第一个数比第二个数大,如果第二个数比第三个数大,那么第一个数肯定比第三个数大,有必要再判断一下第一个数和第三个数的大小吗?
环形队列是必须的,我用两个变量来记录前十个的最小值和倒数第二小的值,两个变量来记录后十个的最小值,每读一次就迭代一次(迭代不是那么简单,有很多细节),当然,这个程序比较复杂,但是要说效率,比LZ的不知道高到哪里去了。

出0入0汤圆

 楼主| 发表于 2014-3-19 14:31:10 | 显示全部楼层
snoopyzz 发表于 2014-3-19 12:47
花了点时间写了个循环队列, LZ看来只能做伸手党了

#include "LIMITS.H"

代码晚上再测试啊,现在要弄别的了

代码一定会测试,是否可用这个帖子都会有一个说明的

多谢写代码啊

出0入0汤圆

 楼主| 发表于 2014-3-19 14:32:22 | 显示全部楼层
mitchell 发表于 2014-3-19 13:45
无用功而已。
LZ是要在采样序列里出现极小值的时候,执行相应的处理代码。
LZ规定的极小值的判断条件是: ...

说的很清楚,多谢

我就是要求一个极小值而已啊

出0入0汤圆

发表于 2014-3-19 14:36:38 | 显示全部楼层
建议楼主用专门的方法来测试测试算法的效率,包括空间复杂度和时间复杂度。你那种是目前最没技术含量也是最臃肿的。

出0入0汤圆

发表于 2014-3-19 14:47:41 | 显示全部楼层
LZ觉得使用直接使用数组,很简单直观。而用滑动窗口的数组的话,要通过索引来计算第几个数据,很复杂是吧。
其实你只要做一个专门的函数来获取对应的数据就行了。
比如
uint8_t ReadSampleData(uint8_t Offset);
将访问数据的方法打包起来,只需要填入第几个数据,自动就会算出真正的数组下标,然后返回缓冲区的数据出来。

通过这个函数隐藏了缓冲区具体实现方式,就算到时候你又改回平移数组的实现方式,那也不要修改别处的代码!!
觉得效率低的话可以用参数宏来代替这个函数~~

出0入0汤圆

发表于 2014-3-19 14:48:09 | 显示全部楼层
snoopyzz 发表于 2014-3-19 12:47
花了点时间写了个循环队列, LZ看来只能做伸手党了

#include "LIMITS.H"

#define ARRAY_COUNT(a)   (sizeof(a)/sizeof(a[0]))
这句宏建议少用,看似方便,简直就是产生Bug的罪魁祸首。
比如我这样:
int asd[123];
int *p=asd;
printf("%d,%d\n",sizeof(asd)/sizeof(int),sizeof(p)/sizeof(int));
语法上,逻辑上都没有错误,但是,程序却给出了不同的结果,换你的程序,什么时候产生个Bug都不知道。

出0入0汤圆

发表于 2014-3-19 14:49:58 | 显示全部楼层
鼻儿眼睛花 发表于 2014-3-19 14:48
#define ARRAY_COUNT(a)   (sizeof(a)/sizeof(a[0]))
这句宏建议少用,看似方便,简直就是产生Bug的罪魁 ...

自己混淆了数组和指针能怪这个宏么?

出0入0汤圆

发表于 2014-3-19 14:51:48 | 显示全部楼层
chencc8 发表于 2014-3-19 14:49
自己混淆了数组和指针能怪这个宏么?

我是使用者,你函数封装了谁知道?现在代码在这儿摆着我看到了,你和人家合作的时候,谁知道?

出0入0汤圆

发表于 2014-3-19 14:55:04 | 显示全部楼层
鼻儿眼睛花 发表于 2014-3-19 14:29
太多重复判断了,根本没有必要,比如,第一个数比第二个数大,如果第二个数比第三个数大,那么第一个数肯 ...

自作聪明。你认为你的代码效率会比LZ位的效率高?再说,你的代码实现了LZ的需求吗?
举个例子,对于以下的序列:
10, 11, 12, 13, 14, 15, 14, 13, 12, 11,      10,       11, 12, 11, 12, 11, 12, 11, 12, 10, 10

按照楼主的要求,极小值判断条件应该为真。你的代码能实现么?

出0入0汤圆

发表于 2014-3-19 14:56:46 | 显示全部楼层
本帖最后由 鼻儿眼睛花 于 2014-3-19 15:00 编辑
mitchell 发表于 2014-3-19 14:55
自作聪明。你认为你的代码效率会比LZ位的效率高?再说,你的代码实现了LZ的需求吗?
举个例子,对于以下 ...


这是最坏的情况,确实会花较多时间,但是,出现的概率又有多大呢?算下来,算法节约的时间多了去了。
再说了,我只说了思路,还有很多技术细节,这些都是要注意的。特殊情况特殊对待。

说错了。你没有理解到我的意思,仅仅是列了一系列数据而已。

出0入0汤圆

发表于 2014-3-19 15:04:53 | 显示全部楼层
鼻儿眼睛花 发表于 2014-3-19 14:51
我是使用者,你函数封装了谁知道?现在代码在这儿摆着我看到了,你和人家合作的时候,谁知道? ...

函数是你自己写的,你会不知道要访问的目标究竟是数组名还是指针?
对于使用全局变量传输进来的数组名OR指针,没有沟通过?

出0入0汤圆

发表于 2014-3-19 15:06:03 | 显示全部楼层
哦,看反了,原来你是使用者~~
你使用这个函数,这个函数要求使用全局的数组名,你定义了一个同名的指针,也不能怪人

出0入0汤圆

发表于 2014-3-19 15:06:36 | 显示全部楼层
鼻儿眼睛花 发表于 2014-3-19 14:56
这是最坏的情况,确实会花较多时间,但是,出现的概率又有多大呢?算下来,算法节约的时间多了去了。
再 ...

你再看看38L的内容。
“LZ规定的极小值的判断条件是:(1)比前8个采样值小;(2)比后8个采样值小;(3)不比前第9、10个采样值大;(4)不比后第9、10个采样值大。”
除非LZ改需求,否则很难有更优化的代码了。

如果只是简单的求最大值最小值,那代码简洁得去了。

出0入0汤圆

发表于 2014-3-19 15:08:02 | 显示全部楼层
chencc8 发表于 2014-3-19 15:04
函数是你自己写的,你会不知道要访问的目标究竟是数组名还是指针?
对于使用全局变量传输进来的数组名OR ...

给别人代码的时候要不要这样注释?

/*****************************
*@breif:
*@para: p,只能为数组,不能为指针
*@return:
*****************************/
void Function(int *p)
{
``````````````````
`````````````````
```````````
}

出0入0汤圆

 楼主| 发表于 2014-3-19 15:08:55 | 显示全部楼层
albert_w 发表于 2014-3-19 14:07
1:好好说下那个极值最终怎么计算的, 其它的慢慢说.
2:加当前位置直接用数组循环比较简单---这就是个环形队 ...


1、极小值的判断条件:(1)比前8个采样值小;(2)比后8个采样值小;(3)不比前第9、10个采样值大;(4)不比后第9、10个采样值大。
     这个中间点和前后的10个点都是动态的,即每进来一个新的AD值,把21个点整体向后移动一位,这样就会把最先进来的AD值移除,
     然后把新的AD值放到最后那位,在这新的21个点中判断中间的那个点是否满足要求,满足就把这个点记下来,不满足不计。依次类推。


例如数组中有21个数:
3593
3583
3568
3511
3457
3381
3349
3303
3263
3225
3199
  3168
3179
3196
3215
3263
3323
3390
3467
3519
3544

新的AD值为:3546

先把21个数向后移动一次,得到的数据如下
         3593(这个数据已被移除)
3583
3568
3511
3457
3381
3349
3303
3263
3225
3199
  3168(这个是中间)
3179
3196
3215
3263
3323
3390
3467
3519
3544
    3546(把新的数据放到这里)

现在比较,中间的3168满足条件,记下3168。
后有新AD值3532

         3593(这个数据已被移除)
         3583(这个数据已被移除)
3568
3511
3457
3381
3349
3303
3263
3225
3199
  3168
3179(这个是中间)
3196
3215
3263
3323
3390
3467
3519
3544
    3546(把新的数据放到这里)
    3532(把新的数据放到这里)

比较发现中间的3179比左边的数3168大,不满足条件,放弃

依次在进来新的AD值按照这样的方法一直下去。




2.循环队列可以解决前面的移动,但是后面的判断我还没想清楚。

3.兄弟太激动了

出0入0汤圆

发表于 2014-3-19 15:10:46 | 显示全部楼层
鼻儿眼睛花 发表于 2014-3-19 15:08
给别人代码的时候要不要这样注释?

/*****************************

不要以为知道个doxygen风格就以为很了不起了,半壶水而已。坛子里的高手多得很。

建议你仔细看看LZ位的代码,了解了LZ的需求了再来讨论。

出0入0汤圆

发表于 2014-3-19 15:12:00 | 显示全部楼层
本帖最后由 chencc8 于 2014-3-19 15:15 编辑
鼻儿眼睛花 发表于 2014-3-19 15:08
给别人代码的时候要不要这样注释?

/*****************************


那是~~全局变量的使用必须沟通清楚!
你在什么时候访问了,你负责读取,还是写入,又或者是读写,有没有多线程(OR 前后台)同时访问,这都要提前定义好。

/*****************************
*@breif:
*@para:[in]data 需要写入的数据
*@return:
*@node:函数中用到的全局数组p,方向是输入
*****************************/

都这样写了,使用者还敢用指针来顶替全局数组,那是该死。

出0入0汤圆

发表于 2014-3-19 15:14:39 | 显示全部楼层
mitchell 发表于 2014-3-19 15:10
不要以为知道个doxygen风格就以为很了不起了,半壶水而已。坛子里的高手多得很。

建议你仔细看看LZ位的 ...

莫激动,我是闲的发慌了,和你们瞎扯扯,快喝点水压压惊。

出0入0汤圆

发表于 2014-3-19 15:14:45 | 显示全部楼层
鼻儿眼睛花 发表于 2014-3-19 14:48
#define ARRAY_COUNT(a)   (sizeof(a)/sizeof(a[0]))
这句宏建议少用,看似方便,简直就是产生Bug的罪魁 ...

指针你也别用了, 操作野指针危害更大...
还有数组也别用了...下标写穿了危害也很大...
都比我这个宏危害大...

和别人合作嘛...一个变量是数组还是指针你既然不想去看清楚,

那么一个指针此时是有效还是无效,  指针/数组下标是否在范围内,  想必你也不会去弄清楚了...

出0入0汤圆

发表于 2014-3-19 15:16:11 | 显示全部楼层
鼻儿眼睛花 发表于 2014-3-19 14:51
我是使用者,你函数封装了谁知道?现在代码在这儿摆着我看到了,你和人家合作的时候,谁知道? ...

指针你也别用了, 操作野指针危害更大...
还有数组也别用了...下标写穿了危害也很大...
都比我这个宏危害大...

和别人合作嘛...一个变量是数组还是指针你既然不想去看清楚,

那么一个指针此时是有效还是无效,  指针/数组下标是否在范围内,  想必你也不会去弄清楚了...

出0入0汤圆

发表于 2014-3-19 15:16:24 | 显示全部楼层
chencc8 发表于 2014-3-19 15:12
那是~~全局变量的使用必须沟通清楚!
你在什么时候访问了,你负责读取,还是写入,又或者是读写,有没有 ...

有道理啦,不和你们扯了,去上课了。

出0入0汤圆

发表于 2014-3-19 15:18:07 | 显示全部楼层
snoopyzz 发表于 2014-3-19 15:16
指针你也别用了, 操作野指针危害更大...
还有数组也别用了...下标写穿了危害也很大...
都比我这个宏危害 ...

额,你发了两遍~这语气得有多重啊~

出0入0汤圆

发表于 2014-3-19 15:19:50 | 显示全部楼层
本帖最后由 snoopyzz 于 2014-3-19 15:21 编辑

1、极小值的判断条件:(1)比前8个采样值小;(2)比后8个采样值小;(3)不比前第9、10个采样值大;(4)不比后第9、10个采样值大。
============
LZ这个限定不像在找曲线的极小值呀,
正确的应该是 下面这样才对吧?
(4)不比第12、13个采样值大。
你是想找一个类似正弦波的最小值吧?
============
我之前以为LZ要找最小值, 我那个代码找不出这种极小值...

出0入0汤圆

 楼主| 发表于 2014-3-19 15:24:28 | 显示全部楼层
本帖最后由 guxingganyue 于 2014-3-19 15:26 编辑

都怪我没说清楚啊。。。。。。。。

我只要找到21个点中满足条件的极小值即可,条件是:他的左右10个点满足条件,AD值是定时采样后得到的,AD数据有大有小,什么情况都有,比如说1ms一个

找极小值的情况可以形象的比做:这里有1万个数据排成一排,我取一个21个数据的作为一个窗口,判断窗口中间的数是否满足我的要求,满足的话就把这个数记下来,不满足不计。这1万数数据除了前面的10个点后面倒数的10个点不满足左右10点外,那剩下的点 每个点都得判断一次看看此点的左右10点是否满足条件

第一次判断第10个点是否满足要求,第二次窗口向前移动一位,判断第11点是否满足要求,这样一直移动,判断下去。。。。。

不是找21个点中单纯的极小值啊。。。。

出0入0汤圆

 楼主| 发表于 2014-3-19 15:29:39 | 显示全部楼层
snoopyzz 发表于 2014-3-19 15:19
1、极小值的判断条件:(1)比前8个采样值小;(2)比后8个采样值小;(3)不比前第9、10个采样值大;(4)不比后第 ...


都怪我没有描述清楚,

条件就是楼主位的条件,52楼mitchell  解释的很正确

条件不能改

出0入0汤圆

发表于 2014-3-19 15:33:15 | 显示全部楼层
guxingganyue 发表于 2014-3-19 15:24
都怪我没说清楚啊。。。。。。。。

我只要找到21个点中满足条件的极小值即可,条件是:他的左右10个点满足 ...



LZ直接说, 是不是要出找这样的红点来?

就是这个极小值要满足
1. 极小值是滑动窗口的中间点
2. 极小值>=左右相邻的各2个点的值
3. 极小值>窗口中其它点的值

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2014-3-19 15:37:48 | 显示全部楼层
snoopyzz 发表于 2014-3-19 15:33
LZ直接说, 是不是要出找这样的红点来?

就是这个极小值要满足

对,我就要找到这个极小值。

极小值<左右各10个点的值,但是左右的第9,第10个点可以和极小值相等。相等的情况说明那个点是下一个极小值了

出0入0汤圆

 楼主| 发表于 2014-3-19 15:42:16 | 显示全部楼层
snoopyzz 发表于 2014-3-19 15:33
LZ直接说, 是不是要出找这样的红点来?

就是这个极小值要满足

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2014-3-19 15:46:25 | 显示全部楼层
guxingganyue 发表于 2014-3-19 15:37
对,我就要找到这个极小值。

极小值

是这样的话, LZ位的代码就有问题了

if((buffer0[10]<=buffer0[0])
&&(buffer0[10]<=buffer0[1])
...
if((buffer0[10]<=buffer0[19])
&&(buffer0[10]<=buffer0[20])

这里显然有问题吧...你比较小于相等的是窗口两侧的, 而不是极小值左右两边的

出0入0汤圆

发表于 2014-3-19 17:11:30 | 显示全部楼层
AD采集,排序,平均值,滤波。

不知道楼主干嘛?

但是排序后,基本就知道最小值在那个位置了。

出0入0汤圆

发表于 2014-3-19 19:01:24 | 显示全部楼层
chencc8 发表于 2014-3-19 15:12
那是~~全局变量的使用必须沟通清楚!
你在什么时候访问了,你负责读取,还是写入,又或者是读写,有没有 ...

完全可以通过工程配置的模块间接口来隐藏这些不必要的干扰的因素的,一个组件写稳定了头文件里面带几句实用说明就行了,根本不用在意实现的.
我本来也准备贴一下我写的CircularQueue,但是好久没用懒得找,又写的不好~

PS:LZ的需求,其实很简单,无非是用ADT的时候看起来麻烦了一点.我完全同意44L的看法,软件写到后来复杂性上去了,不用抽象思维做一下封装,要把所有的功能都映射到基本操作上面去,不是不可以但是太累了.

效率的问题,读写都可以直接一句话操作指针搞定,即使封装函数后,开高优化等级编译器都会帮你内联的,性能损失几乎可以不计的...
顺便,我估计还真没有几个人能写的好环形队列的,包括我自己.

出0入0汤圆

 楼主| 发表于 2014-3-19 20:13:12 | 显示全部楼层
snoopyzz 发表于 2014-3-19 15:46
是这样的话, LZ位的代码就有问题了

if((buffer0[10]

没理解???

出0入0汤圆

 楼主| 发表于 2014-3-19 20:14:41 | 显示全部楼层
Excellence 发表于 2014-3-19 17:11
AD采集,排序,平均值,滤波。

不知道楼主干嘛?

每个数值是有序号的,不能排序,排序后找到的极小值不是我想要的

你还是没有理解我要干嘛

出0入8汤圆

发表于 2014-3-19 20:59:55 | 显示全部楼层
怎么不换个更快的CPU? 或者改FPGA。
感觉这个问题,即使有更快的算法,又能快多少? 如果快1倍能达到你的要求么?

出0入8汤圆

发表于 2014-3-19 21:07:53 | 显示全部楼层
本帖最后由 lw2012 于 2014-3-19 21:48 编辑

我有一个想法, 明天再想想,可能能行。

出0入0汤圆

发表于 2014-3-19 22:12:18 | 显示全部楼层

出0入0汤圆

发表于 2014-3-19 23:21:19 | 显示全部楼层
空间换时间,另外定义一个数组,存放极小值
buffer0[21]
minval[21]
配合循环队列,每次新的AD值进来的时候,更新最后一个极小值,可以用O(1)的时间完成楼主的事情。

出0入0汤圆

发表于 2014-3-19 23:37:11 | 显示全部楼层
本帖最后由 summarize 于 2014-3-19 23:57 编辑

环形队列是可以实现的,只是LZ一直没能理解。我试着能不能说得LZ明白:

1.LZ要先忘记什么下标20,你是目的只是为了方便得到下标10.但只要目的能达到,什么方法已经不重要了。

2.假设LZ开了一个buffer[100]的数组,当第21个数据进来的时候,由下标20-10=10,得到中间下标10,然后可以判断极小值了。

3.当第22个数据进来的时候,由21-10=11,得到中间下标11,然后可以判断极小值了。

4.依次类推,当第N个数据进来的时候,由(N-1)-10求得中间下标,然后判断极小值。

5.当N=101时,N=1,即下标回到起点0,此时就不用(N-1)-10求得中间下标,而应该用  100+(N-1)-10 求得中间下标,然后判断极小值。

6.实际上并不必要定义100个数据元素,因为每次最多只用到21个,上面定义100个是为了不让N-1太快回到起点0,让人不好理解。

7.定义为buffer[21]后,求中间下标的公式如 20楼所说:  x = (index+11)%21;。

出0入0汤圆

发表于 2014-3-20 01:41:19 | 显示全部楼层
  1. static unsigned sBuffer[21];
  2. static unsigned sPointer;
  3. static unsigned sCount;

  4. int AddElementToBuffer(unsigned aElement)
  5. {
  6.     unsigned lVirtualMiddle;
  7.    
  8.     sBuffer[sPointer] = aElement;
  9.     lVirtualMiddle = sPointer + (21+1)/2;
  10.     sPointer += 1;
  11.     sPointer %= 21;
  12.    
  13.     if(sCount<21)
  14.     {
  15.         sCount++;
  16.         return -1;
  17.     }
  18.     else
  19.     {
  20.         unsigned lFlag=0;
  21.         unsigned i;
  22.         
  23.         for(i=(21-1)/2; (i>8)&&(!lFlag); --i)
  24.         {
  25.             if( !(sBuffer[lVirtualMiddle%21] <= sBuffer[(lVirtualMiddle+i)%21]) )
  26.             {
  27.                 lFlag = 1;
  28.             }
  29.             
  30.             if( !(sBuffer[lVirtualMiddle%21] <= sBuffer[(lVirtualMiddle-i)%21]) )
  31.             {
  32.                 lFlag = 1;
  33.             }
  34.         }
  35.         
  36.         for(i=8; (i>0)&&(!lFlag); --i)
  37.         {
  38.             if( !(sBuffer[lVirtualMiddle%21] < sBuffer[(lVirtualMiddle+i)%21]) )
  39.             {
  40.                 lFlag = 1;
  41.             }
  42.             
  43.             if( !(sBuffer[lVirtualMiddle%21] < sBuffer[(lVirtualMiddle-i)%21]) )
  44.             {
  45.                 lFlag = 1;
  46.             }
  47.         }
  48.         
  49.         return lFlag?(-1):sBuffer[lVirtualMiddle%21];
  50.     }
  51. }
复制代码

出0入0汤圆

发表于 2014-3-20 07:50:14 | 显示全部楼层
根本就不需移动  ! 通俗点讲:  把21个单元想象为一个环,每次只修改环上的一个单元的数据,记录当前修改的是哪个单元以便取数,就可以了。

出0入8汤圆

发表于 2014-3-20 08:36:18 | 显示全部楼层
无级电工 发表于 2014-3-20 07:50
根本就不需移动  ! 通俗点讲:  把21个单元想象为一个环,每次只修改环上的一个单元的数据,记录当前修改 ...

如果数据量大的话要用环形队列无疑。
可是现在是21个数据,环形队列还有那么高的效率么?我觉得就得认真想一下才行。

出0入0汤圆

 楼主| 发表于 2014-3-20 08:37:42 | 显示全部楼层
lw2012 发表于 2014-3-19 20:59
怎么不换个更快的CPU? 或者改FPGA。
感觉这个问题,即使有更快的算法,又能快多少? 如果快1倍能达到你的 ...

CPU换不了了

我发这个帖子的目的是看看大家有没有好的方法把我的那些语句简化一下

如果不行的话,也没关系,现在程序跑的挺好的。

出0入8汤圆

发表于 2014-3-20 08:45:42 | 显示全部楼层
guxingganyue 发表于 2014-3-20 08:37
CPU换不了了

我发这个帖子的目的是看看大家有没有好的方法把我的那些语句简化一下

感觉还是应该有更快的算法,但是还没想清楚,有时间了帮你想想。
还有, 你的这个程序是在什么CPU上跑的?
性能极致的程序应该是和CPU相关的。

出0入0汤圆

 楼主| 发表于 2014-3-20 08:52:26 | 显示全部楼层
summarize 发表于 2014-3-19 23:37
环形队列是可以实现的,只是LZ一直没能理解。我试着能不能说得LZ明白:

1.LZ要先忘记什么下标20,你是目的 ...

ls说得很通俗,我好想能理解一些

我对队列不熟悉,得学习后再来理解这个问题

出0入0汤圆

 楼主| 发表于 2014-3-20 08:54:42 | 显示全部楼层
lw2012 发表于 2014-3-20 08:45
感觉还是应该有更快的算法,但是还没想清楚,有时间了帮你想想。
还有, 你的这个程序是在什么CPU上跑的 ...

430上面,能想出更好的方法最好了

我先学习一下队列后再来看看这个问题能否很好的解决

出0入0汤圆

发表于 2014-3-20 19:19:26 | 显示全部楼层
summarize 发表于 2014-3-19 23:37
环形队列是可以实现的,只是LZ一直没能理解。我试着能不能说得LZ明白:

1.LZ要先忘记什么下标20,你是目的 ...

LZ要的不是队列……只是普通的环形滑动窗口数据结构而已(具体名称我也不清楚,但有种滤波叫滑动窗口滤波就和这类似)。
如果是队列,那这个队列是先入先出还是后入先出?

为什么这么多人都叫这叫队列

出0入0汤圆

发表于 2014-3-20 20:52:31 | 显示全部楼层
chencc8 发表于 2014-3-20 19:19
LZ要的不是队列……只是普通的环形滑动窗口数据结构而已(具体名称我也不清楚,但有种滤波叫滑动窗口滤波 ...


它是一个首尾相连的FIFO的数据结构,采用数组的线性空间,数据组织简单。能很快知道队列是否满为空。能以很快速度的来存取数据。

环形队列实现原理 /链式实现 :
http://idsips.blog.163.com/blog/static/48001272201252975126674/

每次AD采样然后存到数组中就是写入队列,判断极小值时,就是取数据(并判断)的过程。

只是,LZ的应用有点特殊。

出0入0汤圆

发表于 2014-3-20 21:35:20 | 显示全部楼层
summarize 发表于 2014-3-20 20:52
它是一个首尾相连的FIFO的数据结构,采用数组的线性空间,数据组织简单。能很快知道队列是否满为空。能以 ...


这玩意没有什么FIFO的,整个结构是一个滑动的窗口,只需要一个写入索引,根据索引就可以知道前几个数据的值是多少。

如果这算是FIFO队列的话,那滑动窗口平均滤波(也叫递推平均滤波)难道也可以叫做是成FIFO队列平均滤波么……

另外FIFO这点还有争议点,假如用我在44L写的接口ReadSampleData(0)来获取当前写入的数据的话,这可以看作是LIFO因为是这个数据是最后写入的,
而用ReadSampleData(20)的话,那就算是FIFO~~

所以这玩意根本算不上是队列。

出0入0汤圆

发表于 2014-3-20 21:48:52 | 显示全部楼层
chencc8 发表于 2014-3-20 21:35
这玩意没有什么FIFO的,整个结构是一个滑动的窗口,只需要一个写入索引,根据索引就可以知道前几个数据的 ...


单片机,全称是单片微型计算机,可是它没有鼠标,没有显示器,怎么能叫计算机呢?

好吧,它不叫环形队列,那请你给它起个名字吧,我可不想和别个沟通时把它叫做 那个什么什么。

出0入0汤圆

发表于 2014-3-22 08:37:27 | 显示全部楼层
summarize 发表于 2014-3-20 21:48
单片机,全称是单片微型计算机,可是它没有鼠标,没有显示器,怎么能叫计算机呢?

好吧,它不叫环形队 ...

不想称之为“滑动窗口平均滤波算法中用到的数据结构”,叫做是队列的话,还是必须说明下这不是普通的队列,
要不然别人看到帖子去学了队列的实现技术,却云里雾里,那就不好了。

不过你还好,至少说明了你的“队列”的实现方式

出0入0汤圆

发表于 2014-3-22 09:28:47 | 显示全部楼层
如果楼主极小值的判断条件是:(1)比前8个采样值小;(2)比后8个采样值小;(3)不比前第9、10个采样值大;(4)不比后第9、10个采样值大。

那么当出来一个极值点后,说明之后的连续8个数据肯定不是极值点了,那就不需要一个一个的往后移动啊,可以一次连续读8个数据,然后再判断。

出0入0汤圆

 楼主| 发表于 2014-4-28 09:57:42 | 显示全部楼层
本帖最后由 guxingganyue 于 2014-4-28 09:59 编辑

多谢楼上各位的回答

最近看了一下队列,自己弄了一个表。

又弄了一个如果使用环形队列时我的比较的所有情况,最后用求通项公式的方法发现,中间点还可以,但是边上点只要翻转时都要加判断,这样写估计比我那样移动快不了多少

再加上阅读性变差,故还是用原先的方法,不用环形队列了。

注:环形队列可以很容易的实现前面的移动,后面的比较就要加翻转判断,但是能实现,又不是很好,所以还用以前的移动方法吧。

编辑原因:下图中第一个data19写错了,其实是data18


H为头指针,R为尾指针,i为头指针对应的数组下标,j为尾小标

  1. H=a[0],R=a[1]
  2. i=0;j=1
  3. if((a[5]<a[0])&&
  4.    (a[5]<a[1])&&
  5.    (a[5]<a[2])&&
  6.    (a[5]<a[3])&&
  7.    (a[5]<a[4])&&//左边
  8.    
  9.    (a[5]<a[6])&&
  10.    (a[5]<a[7])&&
  11.    (a[5]<a[8])&&
  12.    (a[5]<a[9])&&
  13.    (a[5]<a[10]))//右边
  14. H=a[1],R=a[2]
  15. i=1;j=2
  16. if((a[6]<a[1])&&
  17.    (a[6]<a[2])&&
  18.    (a[6]<a[3])&&
  19.    (a[6]<a[4])&&
  20.    (a[6]<a[5])&&//左边
  21.    
  22.    (a[6]<a[7])&&
  23.    (a[6]<a[8])&&
  24.    (a[6]<a[9])&&
  25.    (a[6]<a[10])&&
  26.    (a[6]<a[0]))//右边
  27. H=a[2],R=a[3]
  28. i=2;j=3
  29. if((a[7]<a[2])&&
  30.    (a[7]<a[3])&&
  31.    (a[7]<a[4])&&
  32.    (a[7]<a[5])&&
  33.    (a[7]<a[6])&&//左边

  34.    (a[7]<a[8])&&
  35.    (a[7]<a[9])&&
  36.    (a[7]<a[10])&&
  37.    (a[7]<a[0])&&
  38.    (a[7]<a[1]))//右边
  39. H=a[3],R=a[4]
  40. i=3;j=4
  41. if((a[8]<a[3])&&
  42.    (a[8]<a[4])&&
  43.    (a[8]<a[5])&&
  44.    (a[8]<a[6])&&
  45.    (a[8]<a[7])&&//左边

  46.    (a[8]<a[9])&&
  47.    (a[8]<a[10])&&
  48.    (a[8]<a[0])&&
  49.    (a[8]<a[1])&&
  50.    (a[8]<a[2]))//右边
  51. H=a[4],R=a[5]
  52. i=4;j=5
  53. if((a[9]<a[4])&&
  54.    (a[9]<a[5])&&
  55.    (a[9]<a[6])&&
  56.    (a[9]<a[7])&&
  57.    (a[9]<a[8])&&//左边

  58.    (a[9]<a[10])&&
  59.    (a[9]<a[0])&&
  60.    (a[9]<a[1])&&
  61.    (a[9]<a[2])&&
  62.    (a[9]<a[3]))//右边
  63. H=a[5],R=a[6]
  64. i=5;j=6
  65. if((a[10]<a[5])&&
  66.    (a[10]<a[6])&&
  67.    (a[10]<a[7])&&
  68.    (a[10]<a[8])&&
  69.    (a[10]<a[9])&&//左边

  70.    (a[10]<a[0])&&
  71.    (a[10]<a[1])&&
  72.    (a[10]<a[2])&&
  73.    (a[10]<a[3])&&
  74.    (a[10]<a[4]))//右边
  75. H=a[6],R=a[7]
  76. i=6;j=7
  77. if((a[0]<a[6])&&
  78.    (a[0]<a[7])&&
  79.    (a[0]<a[8])&&
  80.    (a[0]<a[9])&&
  81.    (a[0]<a[10])&&//左边

  82.    (a[0]<a[1])&&
  83.    (a[0]<a[2])&&
  84.    (a[0]<a[3])&&
  85.    (a[0]<a[4])&&
  86.    (a[0]<a[5]))//右边
  87. H=a[7],R=a[8]
  88. i=7;j=8
  89. if((a[1]<a[7])&&
  90.    (a[1]<a[8])&&
  91.    (a[1]<a[9])&&
  92.    (a[1]<a[10])&&
  93.    (a[1]<a[0])&&//左边

  94.    (a[1]<a[2])&&
  95.    (a[1]<a[3])&&
  96.    (a[1]<a[4])&&
  97.    (a[1]<a[5])&&
  98.    (a[1]<a[6]))//右边
  99. H=a[8],R=a[9]
  100. i=8;j=9
  101. if((a[2]<a[8])&&
  102.    (a[2]<a[9])&&
  103.    (a[2]<a[10])&&
  104.    (a[2]<a[0])&&
  105.    (a[2]<a[1])&&//左边

  106.    (a[2]<a[3])&&
  107.    (a[2]<a[4])&&
  108.    (a[2]<a[5])&&
  109.    (a[2]<a[6])&&
  110.    (a[2]<a[7]))//右边
  111. H=a[9],R=a[10]
  112. i=9;j=10
  113. if((a[3]<a[9])&&
  114.    (a[3]<a[10])&&
  115.    (a[3]<a[0])&&
  116.    (a[3]<a[1])&&
  117.    (a[3]<a[2])&&//左边

  118.    (a[3]<a[4])&&
  119.    (a[3]<a[5])&&
  120.    (a[3]<a[6])&&
  121.    (a[3]<a[7])&&
  122.    (a[3]<a[8]))//右边
  123. H=a[10],R=a[0]
  124. i=10;j=0
  125. if((a[4]<a[10])&&
  126.    (a[4]<a[0])&&
  127.    (a[4]<a[1])&&
  128.    (a[4]<a[2])&&
  129.    (a[4]<a[3])&&//左边

  130.    (a[4]<a[5])&&
  131.    (a[4]<a[6])&&
  132.    (a[4]<a[7])&&
  133.    (a[4]<a[8])&&
  134.    (a[4]<a[9]))//右边
  135.    
  136. H=a[0],R=a[1]
  137. i=0;j=1
  138. if((a[5]<a[0])&&
  139.    (a[5]<a[1])&&
  140.    (a[5]<a[2])&&
  141.    (a[5]<a[3])&&
  142.    (a[5]<a[4])&&//左边
  143.    
  144.    (a[5]<a[6])&&
  145.    (a[5]<a[7])&&
  146.    (a[5]<a[8])&&
  147.    (a[5]<a[9])&&
  148.    (a[5]<a[10]))//右边

  149. //中间的值
  150. if(i+5>10)
  151. {
  152.   a[i+5-11];
  153. }
  154. else
  155. {
  156.   a[i+5];
  157. }

  158. //两边的值
  159. //只要j+5>10,就涉及下标的判断
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2014-7-3 09:03:57 | 显示全部楼层
整个 环形队列可以吧~~~  rear 和 front ~ 

不用移动数据,只移动下标(也就是偏移地址)

可用 结构体 定义,
Q.front = ((Q.rear+1)%SIZEQUEUE);

也可以用 数组直接定义。

出0入0汤圆

发表于 2014-7-3 10:25:05 | 显示全部楼层
不晓得这样内存搬家算不算快的。就是要搬两次。
  1. #include <string.h>

  2. u8 *RtnBuffer(u8 srcBuffer[21])
  3. {
  4.         u8 tmpBuffer[20] = {0};
  5.        
  6.         memcpy(tmpBuffer, &srcBuffer[1], 20);
  7.         memcpy(&srcBuffer[0], tmpBuffer, 20);
  8.         return srcBuffer;
  9. }


  10. void  Function(void)
  11. {
  12.         u8 buffer0[21] = {0};
  13.         RtnBuffer( buffer0 );
  14. }
复制代码

出0入0汤圆

发表于 2014-7-3 10:29:08 | 显示全部楼层
你是要数字滤波吗?  用你开题的方法 不管怎么样效率都低

出0入0汤圆

 楼主| 发表于 2014-7-3 10:50:26 | 显示全部楼层
xf331785508 发表于 2014-7-3 10:25
不晓得这样内存搬家算不算快的。就是要搬两次。

memcpy 内部用了循环,效果没有直接移动好。


再次感谢各位的讨论,算法已经改用其他方法了,这个没有使用了。

分数给谁呢?要不就先回答的比较好就给谁吧

出0入0汤圆

发表于 2014-7-3 11:47:14 | 显示全部楼层
奇怪了 恢复不了啊

出0入0汤圆

发表于 2014-7-3 11:47:32 | 显示全部楼层
额 基于这21个已经采样到的数据来讲,不好做优化啊,可不可以这样,LZ需要找的极小值,那么总是存在两个单边,极小值的判断总是伴随着一个连续的下降沿和一个连续的上升沿

出0入0汤圆

发表于 2014-7-3 11:47:56 | 显示全部楼层
那么问题可以简化为判断10个采样点的连续下降沿,如果采样到是个连续的下降沿,则执行后续判断(10个点连续的上升沿),

出0入0汤圆

发表于 2014-7-3 11:48:30 | 显示全部楼层
那么问题可以简化为判断10个采样点的连续下降沿,如果采样到是个连续的下降沿,则执行后续判断(10个点连续的上升沿),

出0入0汤圆

发表于 2014-7-3 12:51:01 | 显示全部楼层
否者前10个点只要出现后续点比前一个点的值大,说明出现了一个上升沿或者上升脉冲,这种点一出现,表明条件不满足,直接毁掉前边保存的数据
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-23 15:29

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表