注册 登录
编程论坛 C语言论坛

C语言寻找一组数据中的第一第二峰值

zzmx 发布于 2020-02-11 12:14, 6750 次点击
实验要求,我需要找出一组数组中的两个峰值:第一个峰值和第二个峰值及其数组下标。这组数据画出的图应该是这样的,我就要找出图中的那两个峰值
只有本站会员才能查看附件,请 登录

我写的程序如下,我试了一下,这样找出的数据是不对的。比如有的数据会找出这样的数(隔得太近了,肯定不是)
只有本站会员才能查看附件,请 登录
有的会找出这样的数
只有本站会员才能查看附件,请 登录

所以,请问有没有办法找出这样的两个峰值。
程序代码:

#include <iostream>
int main(int argc, char** argv)
 {
     double a[3000];
     double peak1,peak2,min=a[0];
     int i,p1,p2,t1,t2,life;
     FILE *fp=NULL;
     FILE *fpp=NULL;
     fp=fopen("G:\\uz\\new\\data100578.txt","r");
     for(i=0;i<2500;i++)
     {
         fscanf(fp,"%lf",&a[i]);
     }
     for(i=1;i<2500;i++)
     {
         if(a[i]<min)
         {
         min=a[i];
        peak1=a[i];
         p1=i+1;   
         }
     }//找第一个峰值
     
     for(i=p1,min=a[p1];i<2500;i++)
     {
         if(a[i]<min)
         {
         min=a[i];
         peak2=a[i];
         p2=i+1;   
         }
     }//找第二个峰值
     printf("%lf %d\n",peak1,p1);
    printf("%lf %d\n",peak2,p2);
     fclose(fp);
    return 0;
}

附几组数据
只有本站会员才能查看附件,请 登录


[此贴子已经被作者于2020-2-11 12:19编辑过]

38 回复
#2
叶纤2020-02-11 19:42
楼主最好不要把c++语法和c语言语法混淆。
我测试是正好
还有fopen对于我来说是新知识,并没有太多认知,如果你fopen,那写错我也看不出来了,我没学过
程序代码:
  #include <iostream>
int main()
{
    double a[3000]= {};
    double peak=0,peak_2=0,min=a[0],mina=a[0];
    int i=0,p1=0,p2=0,t1=0,t2=0,life=0;
    FILE *fp=NULL;
    FILE *fpp=NULL;
    fp=fopen("G:\\uz\\new\\data100578.txt","r");


    for(i=1; i<sizeof(a)/sizeof(double); i++)
    {
        if(min>a[i])
        {
            min =a[i];
            p1=i+1;
        }
    }
    a[p1-1]=a[(sizeof(a)/sizeof(double))-1];
    a[(sizeof(a)/sizeof(double))-1]=a[p1-1];
    for(i=1; i<sizeof(a)/sizeof(double); i++)
    {
        if(mina>a[i])
        {
            mina =a[i];
            p2=i+1;
        }
    }

    std::cout<<min<<"\t"<<"xiabiao"<<"\t"<<p1;
    std::cout<<'\n';
    std::cout<<mina<<"\t"<<"xiabiao"<<"\t"<<p2;
    fclose(fp);
    return 0;
}   

#3
纯蓝之刃2020-02-11 21:10
程序代码:
#include <stdio.h>
#define Threshold -10            //设置阈值
int main(int argc, char** argv)
{
    float a[3000];
    float peak1,peak2,peak2_1,peak2_2,min=a[0];
    int i,p1,p2,p2_1,p2_2,t1,t2,life;
    FILE *fp=NULL;
    FILE *fpp=NULL;
    fp=fopen("F:\\data\\data100000.txt","r");
    for(i=0; i<2500; i++)
    {
        fscanf(fp,"%f",&a[i]);
        //printf("%d-%f\n",i,a[i]);
    }
    for(i=0; i<2500; i++)
    {
        if(a[i]<min)
        {
            min=a[i];
            peak1=a[i];
            p1=i;
            printf("min=%f,p1=%d\n",peak1,p1);
        }
    }//找最大的峰值

    for(i=p1; i>0; i--)         //以第一个极值为基准,将数据分为两部分处理
    {
        if(a[i]>Threshold)
        {
            t1=i;
            break;
        }
    }
    for(i=p1; i<2500; i++)
    {
        if(a[i]>Threshold)
        {
            t2=i;
            break;
        }
    }

    min=0;
    for(i=0; i<t1; i++)
    {
        if(a[i]<min)
        {
            min=a[i];
            peak2_1=a[i];
            p2_1=i;
            printf("min=%f,p2_1=%d\n",peak2_1,p2_1);
        }
    }
    min=0;
    for(i=t2; i<2500; i++)
    {
        if(a[i]<min)
        {
            min=a[i];
            peak2_2=a[i];
            p2_2=i;
            printf("min=%f,p2_2=%d\n",peak2_1,p2_1);
        }
    }

    if(peak2_1<peak2_2)                             //分别处理的两部分结果比较,取最值
    {
        peak2=peak2_1;
        p2=p2_1;
    }
    else
    {
        peak2=peak2_2;
        p2=p2_2;
    }

    printf("%f %d\n",peak1,p1+1);
    printf("%f %d\n",peak2,p2+1);
    fclose(fp);
    return 0;
}

#4
叶纤2020-02-11 21:42
回复 5楼 纯蓝之刃
浮点数小数点后位数多了,精度也会变啊

[此贴子已经被作者于2020-2-11 22:35编辑过]

#5
叶纤2020-02-11 21:46
还有怎么开小数点后那么多位的?我也想开,
突然发现我的代码下标忘加1了

[此贴子已经被作者于2020-2-11 21:50编辑过]

#6
xianfajushi2020-02-11 22:32
之前发的图片也觉得数据奇怪,查文件数据内容,发现数据没读到,暂不跟帖,希望理解一下,
以下是引用叶纤在2020-2-11 21:46:34的发言:



修改了一下已经读到数据,0文件获得2个数据:
只有本站会员才能查看附件,请 登录


#7
xianfajushi2020-02-11 22:32
读1文件获得2个位置:
只有本站会员才能查看附件,请 登录


[此贴子已经被作者于2020-2-11 22:34编辑过]

#8
叶纤2020-02-11 23:02
回复 7楼 xianfajushi
                。。。。。。

[此贴子已经被作者于2020-2-11 23:20编辑过]

#9
xianfajushi2020-02-11 23:44
文件0找到的2个位置似乎与图片上的一样,文件1不知是否对?待贴主回复看看。
分析波形的数据不易,波形数据是复杂的,假如波形未爬升到0又下降形成另一个波谷,算不算要找的?这是要说明清楚的。

波形数据是复杂的,要把典型的波形图例举出来,说明需要分析的所有条件限制,才能设计出符合的程序,简单的分析是不够的;

[此贴子已经被作者于2020-2-12 08:20编辑过]

#10
叶纤2020-02-12 12:11
回复 9楼 xianfajushi
我找的峰值和您的一样,不过2文件的下标和您的有偏差,还有光靠1文件的波形图并不能总结出什么,
我和您一样脑中有很多如果如果,感觉第二个峰值为-10太狗血了,等我有空的时候再改个我认为行的方案
-453.604000     xiabiao 1160
-10.895800      xiabiao 450
#11
xianfajushi2020-02-12 13:45
提供的文件编号0、1、2,2的文件找到如下
只有本站会员才能查看附件,请 登录

分析一下3个文件数据,发现0文件2个标准谷,1文件2个非标准谷,2文件只有1谷。贴主确认一下看是否?

[此贴子已经被作者于2020-2-12 13:59编辑过]

#12
叶纤2020-02-12 13:58
回复 11楼 xianfajushi
我改变了下代码
0文件
-313.630000     xiabiao 1575
-307.120000     xiabiao 96
1文件
-453.604000     xiabiao 1160
-300.609000     xiabiao 1250
2文件
-359.203000     xiabiao 338
-196.443000     xiabiao 429
分析一下3个文件数据,发现0文件2个标准谷,1文件2个标准谷,2文件谷峰离和谷腰离的太近,一个标准谷。

[此贴子已经被作者于2020-2-12 14:11编辑过]

#13
xianfajushi2020-02-12 14:05
1和2文件后第二个位置只怕是上升过程的,未必是另一个谷底。
以下是引用叶纤在2020-2-12 13:58:32的发言:
我改变了下代码
0文件
-313.630000     xiabiao 1575
-307.120000     xiabiao 96
1文件
-453.604000     xiabiao 1160
-300.609000     xiabiao 1250
2文件
-359.203000     xiabiao 338
-196.443000     xiabiao 429

#14
叶纤2020-02-12 14:28
回复 13楼 xianfajushi
我画了一下三个文件的波形图,可能我分析的有错吧
只有本站会员才能查看附件,请 登录
#15
叶纤2020-02-12 14:40
以下是引用xianfajushi在2020-2-12 14:05:21的发言:

1和2文件后第二个位置只怕是上升过程的,未必是另一个谷底。

题目目的就是找两个峰值,就是找出最尖尖的那一部分,并没有考虑上升或下降,只要找到最尖尖的那一部分就行了,就像我楼上发的图,自己想的仍是自己想的,还是看数据说话比较实在

[此贴子已经被作者于2020-2-12 14:43编辑过]

#16
吹水佬2020-02-12 16:09
0文件:
-313.630000, 1575行
-310.375000, 1572行

1文件:
-453.604000, 1160行
-450.349000, 1165行

2文件:
-359.203000, 338行
-355.948000, 339行
#17
xianfajushi2020-02-12 16:28
我觉得题目有偏颇,应该是找谷值,且未必每个文件数据都是2个谷值。
我说的标准谷为谷顶数据0为界,非标准谷底为谷顶未回到0以上就又下降。
我说的是要把寻找谷值的条件界定清楚,因为一个谷值有下降沿和上升沿是要定义清楚的,就是说未回到数据为0又下降的算不算是另一个谷值,又谷值的幅度到底定义为多少。
思路未明确,设计的程序找到的数据就会大不相同,只有明确了需要的所有定义,才能编写出正确的处理程序。
提供的数据谷的下降沿和上升沿不是直线的,而是2个沿线过程中有上升和下降的。

文件2的337至341之间只能算是类似一个平底。

[此贴子已经被作者于2020-2-12 17:02编辑过]

#18
叶纤2020-02-12 17:39
我以为我理解有问题,我特意把峰值,正峰值,负峰值,峰谷值,峰峰值,谷值,最大值,最小值看了个遍,顺便看了平值,
#19
xianfajushi2020-02-13 07:53
新思路设计的3个文件找到的谷值倒序输出,花费这2天时间,绞尽脑汁,彻夜难眠,很辛苦才写出来,一遍历即可得整个数据的所有下降沿上升沿谷口。
只有本站会员才能查看附件,请 登录



[此贴子已经被作者于2020-2-13 12:32编辑过]

#20
叶纤2020-02-13 13:38
回复 19楼 xianfajushi
我看您文件2的数据好像有点模糊不定
我给您张图吧我的文件2
-359.203000     xiabiao 338
-53.213500      xiabiao 1559
文件2图
只有本站会员才能查看附件,请 登录

#21
xianfajushi2020-02-13 16:14
改变参数为50就找到了,这个早知道了,上图参数为100的3个文件的输出,改为50则0和1不变,2就是这样的,用表格软件做出图像?我只是调试观察到的数据,用表格做出图像是比较形象。
用我博客发出来的以0为界的程序基本是可以找到标准的波形,就是对1文件的波形找不准,改变界限为10没测试过;
只有本站会员才能查看附件,请 登录

新思路程序对任何波形都可以,若再改变参数的话,会发现更多的谷值。如下图是0文件的,不妨改变一下显示的细节看看对?
只有本站会员才能查看附件,请 登录


[此贴子已经被作者于2020-2-13 16:50编辑过]

#22
叶纤2020-02-13 16:50
以下是引用xianfajushi在2020-2-13 16:14:21的发言:

改变参数为50就找到了,这个早知道了,上图参数为100的3个文件的输出,改为50则0和1不变,2就是这样的,用表格软件做出图像?我只是调试观察到的数据,用表格做出图像是比较形象。

估计楼主更想看到您正确的代码,而非图片和结果
#23
xianfajushi2020-02-13 16:52
这么多天,贴主根本就没反应,用博客的程序修改参数看看?!
#24
叶纤2020-02-13 17:01
回复 23楼 xianfajushi
程序代码:
  
//变成这样的吗?会不会很累?
int 数重组位最大(int 整数)
{       /*C++任意输入一个整数,再把它的各位数字重新组合一个新的整数,使其值最大*///缘由https://bbs.bccn.net/viewthread.php?tid=499134&pid=2718301&page=1#pid2718301
    int 输入整数 = 整数, 数(0), 输出(0), 取值(0), 比较(0), 暂存(0), 位(0), 序(0), 反向(0);
    bool 控制(true);
    if (输入整数 < 100)输入整数 *= 10;
    if (输入整数 > 1000)输入整数 /= 10;
    //scanf_s("%d", &输入整数);
    do
    {
        比较 = 序 = 0;
        暂存 = 输入整数;
        do
        {
            取值 = 暂存 % 10;
            if (取值 > 比较)/*每次取最大值*/
            {
                比较 = 取值;
                数 = 序;
            }
            ++序;
        } while (暂存 /= 10);
        if (控制) 位 = 反向 = 序;
        输出 += 比较 * pow(10, --位);
        控制 = false;
    } while (输入整数 -= 比较 * pow(10, 数));/*每次减去最大值*/
    //printf_s("%d ", 输出);
    数 = 0; 取值 = 输出;
    do
    {
        数 += (输出 % 10) * pow(10, --反向);
    } while (输出 /= 10);/*反向输出各位数*/
    //printf_s("%d ", 数);
    cout << 取值 << "-" << 数 << "=" << 取值 - 数 << endl;
    return 取值 - 数;
}
  
#25
xianfajushi2020-02-13 18:00
不明白你说虾米,https://blog.bccn.net/xianfajushi/66967
以下是引用叶纤在2020-2-13 17:01:28的发言:  

#26
叶纤2020-02-13 18:23
以下是引用xianfajushi在2020-2-13 18:00:35的发言:

不明白你说虾米,https://blog.bccn.net/xianfajushi/66967

我也替你宣传宣传吧
程序代码:
   void 获取2个谷值()
{
    double 读数据[3000]{0}, 谷值[3]{0};
    char* 文件 = "..\\测试存文件\\data100000.txt";
    文件读取(文件, "r", 读数据, 3000);
    int 序 = 0, 数序1 = 0, 数序2 = 0, 数序3 = 0, 谷口 = 0;

 
    while (序 < 3000)
    {//缘由https://bbs.bccn.net/viewthread.php?tid=499186&page=1&extra=#pid2718585
        if (谷值[0]>读数据[序])
            谷值[0] = 读数据[序], 数序1 = 序;
        ++序;
    }
    printf_s("%f->%d\n", 谷值[0], 数序1);
    序 = 数序1;    while (读数据[--序] < 0); 谷口 = 序; 序 = 0;
    while (序 < 谷口)
    {
        if (谷值[1]>读数据[序])
            谷值[1] = 读数据[序], 数序2 = 序;
        ++序;
    }
    序 = 数序1; while (读数据[++序] < 0);
    while (序 < 3000)
    {
        if (谷值[2]>读数据[序])
            谷值[2] = 读数据[序], 数序3 = 序;
        ++序;
    }
    if (谷值[1]<谷值[2])
        printf_s("%f->%d\n", 谷值[1], 数序2);
    else
        printf_s("%f->%d\n", 谷值[2], 数序3);
}
   
#27
zzmx2020-02-14 00:08
谢谢你们的回复。这些数据本身就很复杂,确实存在有多个峰值的可能,我要做的就是找出第一二大峰值,是处理数据最关键的一步。明天我会上线找各位请教!谢谢你们!
#28
zzmx2020-02-14 00:23
这是我不成熟的暂时作为寻峰的代码,偶然性较大。还请大神指教新法。我的思路:第一个循环:找最大值 。第二个循环:从这个最大值后面第200个数开始往后找,再找一个最大值 。第三个循环:从这个最大值前面第200个数开始往前找,再找一个最大值。   最后判断一下:确定第二个峰,但是判断的方法不好确定(一种思路是拿阈值卡,一种思路是比较他们两个的大小,但是这都不是绝对的,万无一失的,因为很多组(1000多)数据的变化是很多样的。总之,这种方法的偶然性较大(全看这个波形是怎么变的),所以不大成熟
程序代码:

#include <iostream>
#include <math.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */

int main(int argc, char** argv)

 {
     double a[3000];
     double peak1,peak2,peak3,min=a[0];
     int i,p1,p2,p3,b,life;
     char filename[1000]={0};
     FILE *fp=NULL;
     FILE *fpp=NULL;
     for(b=100000;b<100854;b++)
     {
         sprintf(filename,"F:\\uz\\new\\data%d.txt",b);
         fp=fopen(filename,"r");
     
     for(i=0;i<2500;i++)
     {
         fscanf(fp,"%lf",&a[i]);
     }
     for(i=1;i<2500;i++)
     {
         if(min>a[i])
         {
         min=a[i];
        peak1=a[i];
         p1=i+1;   
         }
     }//找最小值
     
     for(i=p1+300,min=a[p1+300];i<2500;i++)
     {
         if(min>a[i])
         {
         min=a[i];
        peak2=a[i];
         p2=i+1;   
         }
     }//找第二个峰值
     for(i=p1-300,min=a[p1-300];i>0;i--)
     {
         if(min>a[i])
         {
         min=a[i];
        peak3=a[i];
         p3=i+1;   
         }
     }//找第三个峰值
    /* printf("%lf  %d\n",peak1,p1);
     printf("%lf  %d\n",peak2,p2);
     printf("%lf  %d\n",peak3,p3);
*/
     
     if(peak2>peak3)
     {
     life=abs(p2-p1);   
     //printf("%d\n",life);   
     }
     else
     {
     life=abs(p2-p1);   
         
     //printf("%d\n",life);   
     }
     fpp=fopen("F:\\uz\\life1.txt","a");
     if(fpp==NULL)
     {
         printf("wrong");
     }
     fprintf(fpp,"%d\n",life);
     fclose(fp);
     fclose(fpp);
   }
    return 0;
}

   
#29
吹水佬2020-02-14 08:50
要求顶拐点到底拐点是多少(落差)才算是峰?

[此贴子已经被作者于2020-2-14 08:52编辑过]

#30
xianfajushi2020-02-14 10:13
固定地往前后200个数据不妥,有可能漏掉数据,我花费2天时间写了2个程序,一个就是用大概2次遍历思路是往前后找顶,再从前后顶去找谷,我这个程序只要变动顶的值就能找到不同顶的谷了,比如把0改为20即可,可以说程序思路是对了,另一个程序则是一遍历即可自动推断顶底的,可能还要优化一下。
目前2个程序都只是初稿,都需要优化。

[此贴子已经被作者于2020-2-14 11:18编辑过]

#31
zzmx2020-02-14 13:17
回复 30楼 xianfajushi
你好,我想知道你写的程序结果如何?具体代码是怎么样的?
#32
zzmx2020-02-14 13:19
回复 11楼 xianfajushi
确实会有2文件这种情况,所以在处理数据时,这种波形是需要丢掉的,但是不知道代码怎么实现
#33
zzmx2020-02-14 13:21
回复 11楼 xianfajushi
确实会有这种情况,那这组数据就需要丢掉,但是编程不知道怎么鉴别出这些错误的情况,怎么舍去
#34
zzmx2020-02-14 13:23
回复 29楼 吹水佬
什么意思?我要找的是两个峰值
#35
xianfajushi2020-02-14 13:29
我写的程序结果都发图片出来了,代码看25或26楼的,博客里面代码稍加修改了一下。
需要丢掉什么样的数据请以0、1、2编号文件指出是哪个编号的文件的哪些数据需要丢掉。
以下是引用zzmx在2020-2-14 13:21:41的发言:


[此贴子已经被作者于2020-2-14 13:40编辑过]

#36
叶纤2020-02-14 13:52
回复 35楼 xianfajushi
版主大大,小女子愚昧,能否把你电脑中可以运行的代码直接复制粘贴一下,也让大家运行运行一下
#37
zzmx2020-02-14 14:04
回复 35楼 xianfajushi
是呀!想看你的代码
#38
xianfajushi2020-02-14 14:37
博客发出来的代码就是可以运行的,假如1文件的另一个谷值是不需要的,那么,博客的就是,另一种则不适用因为处理非0谷口。
未正面与我交流回答我的提问,不知给哪个程序。
先用博客的程序,我用C++所以读文件的写法不同,就不给了,处理则大同小异,读数据就用你们自己的了,处理用博客代码。
以下是引用叶纤在2020-2-14 13:52:24的发言:

以下是引用zzmx在2020-2-14 14:04:53的发言:是呀!想看你的代码



[此贴子已经被作者于2020-2-14 14:50编辑过]

#39
吹水佬2020-02-14 17:06
以下是引用zzmx在2020-2-14 13:23:39的发言:

什么意思?我要找的是两个峰值

是不是这样理解,峰值取决于顶拐点到底拐点的落差。
1