找出最小值的问题?

发表于:2007-05-26来源:作者:点击数: 标签:
110 29 310 411 510 69 711 810 911 1010 118 127 135 143 150 161 172 184 195 207 219 2210 2311 2410 2511 第2列数据值大致是开始下降,然后增加的一个变化趋势! 所以希望: 找出最小值,并且在最小值的后面数据,找出第一个比最小值大于3的数据的位置!

1 10
2 9
3 10
4 11
5 10
6 9
7 11
8 10
9 11
10 10
11 8
12 7
13 5
14 3
15 0
16 1
17 2
18 4
19 5
20 7
21 9
22 10
23 11
24 10
25 11

第2列 数据值 大致  是开始下降,然后增加的一个变化趋势!

所以希望:
找出最小值 ,并且 在最小值的后面数据,找出第一个  比最小值 大于3 的数据   的位置!

 mocou 回复于:2005-06-10 23:45:16
偶是找出最小值大4的数
[quote:b868ff14a7]# cat file
1 10 
2 9 
3 10 
4 11 
5 10 
6 9 
7 11 
8 10 
9 11 
10 10 
11 8 
12 7 
13 5 
14 3 
15 0 
16 1 
17 2 
18 4 
19 5 
20 7 
21 9 
22 10 
23 11 
24 10 
25 11[/quote:b868ff14a7]

[code:1:b868ff14a7]结果
# ./scripts
0 18[/code:1:b868ff14a7]

[code:1:b868ff14a7]# cat scripts
aa=$(awk 'BEGIN{temp=0;}{if($2<temp){temp=$2;}}END{aa=$temp;print temp;}' file)
bb=$(awk '/'"\<$aa\>"'/{print $1;exit}' file)
cc=$(expr "$aa" + 4)
dd=$(awk '$2=='"$cc"'{if (NR>="$cc")print $1;exit}' file)
echo "$aa $dd"[/code:1:b868ff14a7]
很笨。。。。。左边是最小值,后边是比最小值大三的数,且在最小值之后的数。

不知道如果最小值有几个要取哪一个?偶这里都取第一个匹配滴

 dbcat 回复于:2005-06-11 13:38:28
最小值:
awk '{print $2}' file | sort -n | head -1
位置:
awk '{print $2}' 2 | sort -n | head -1 |xargs -i expr
{} + 4 |xargs -i awk '{if($2~/{}/)print $1}' 2

 icesummit 回复于:2005-06-11 14:32:36
[quote:9c42fb3fb7="dbcat"]最小值:
awk '{print $2}' file | sort -n | head -1
位置:
awk '{print $2}' 2 | sort -n | head -1 |xargs -i expr
{} + 4 |xargs -i awk '{if($2~/{}/)print $1}' 2[/quote:9c42fb3fb7]

pfpf :!: 不过不能用~应该用==
if($2=={}/) :mrgreen:

 zleil 回复于:2005-06-11 20:25:36
BEGIN{ i=0; j=0; min=0; b3=0;}
{
if( i == 0 ){
    min = $2;
    i ++;
}else{
    if( $2 < min ){
        min = $2;
        j = 0;
    }else{
        if( j == 0 && $2 - min > 3){
            j = 1;
            b3 = $2;
        }
    }
}
}
END{ print "min=" min " b3=" b3; }

有语法错误吗?

 w123456 回复于:2005-06-13 10:01:42
awk '{print $2}' 2    


这里的2是什么意思?

 guangzongy 回复于:2005-06-13 10:26:03
[code:1:304b10974d]
awk '{if (NR==1) {min=$2;dat=$0;flag=1;} if ($2<min) {min=$2;dat=$0;flag=1;} if($2>(min+2)&&flag=
=1) {tag=NR;flag=0}}END{print "MIN item:"dat;print "TAG rowNo:"tag}' yourFile
[/code:1:304b10974d]

 w123456 回复于:2005-06-13 10:40:49
新的要求:

求由最小值 恢复到80%平均值水平的时间差

数列的平均值为 7.76 
7.76 * 80%=6.2 

所以从最小值0 到 7  (第1次超过 6.2 )  的时间差为 20-15=5

 w123456 回复于:2005-06-13 10:44:28
dbcat   icesummit 
 不能排序的。

排序就对时间顺序大乱了,
“在最小值的后面数据,找出第一个  比最小值”  这一条件就无法实现了

 mocou 回复于:2005-06-13 10:47:04
偶的行不行,看到几位前辈的贴了了,偶都汗颜了

 guangzongy 回复于:2005-06-13 11:22:22
分了两步完成 :oops: 
[code:1:2582d80382]
#get min data and avg*80% data.
result=(`awk '{if(NR==1) min=$2; if(min>$2) min=$2;sum+=$2}END{print min" "sum/NR*0.8}' yourFile`)
#get the tag time.
awk '{if($2=='${result[0]}') {startPos=$1;flg="true";} if(flg=="true"&&$2>'${result[1]}') {print
$1-startPos;exit;}}' yourFile
[/code:1:2582d80382]

 guangzongy 回复于:2005-06-13 11:27:43
[quote:3e7152dee9="mocou"]偶的行不行,看到几位前辈的贴了了,偶都汗颜了[/quote:3e7152dee9]
条条大路通罗马 :mrgreen: 
BTW:[color=red:3e7152dee9]前辈[/color:3e7152dee9] :em06: ,估计几位大侠们会被叫得走不动道的 :em06:  :mrgreen:

 w123456 回复于:2005-06-13 16:22:52
多谢 guangzongy

 begincwcw 回复于:2005-06-13 16:26:13
试试这个:
cat filename:
1 10 
2 9 
3 10 
4 11 
5 10 
6 9 
7 11 
8 10 
9 11 
10 10 
11 8 
12 7 
13 5 
14 3 
15 0 
16 1 
17 2 
18 4 
19 5 
20 7 
21 9 
22 10 
23 11 
24 10 
25 11 

程序如下:

nawk '{ line[NR] = $2 }
END{ for(i = 1; i <= NR; i++){
        avg += line[i] 
        if(m == 0)
            min = line[i] 
        else
            if(line[i] < min){
                min = line[i]
                x = i }
        m++ }
for(n = x; n <= NR; n++){
    if( line[n] - min > 3)
        break
    }
for(n1 = x; n1 <= NR; n1++){
    if( line[n1]  > avg / NR  *  0.8 )
        break
    }
{ printf("\n\n最小值为: %s\n第一个比最小值大于3 的数据位置是: %s行\n由最小值恢复到80%平均值水平的时间差为: %s秒 \n\n\n", min, n, n1 - x) }}'  filename

运行结果:

最小值为: 0
第一个比最小值大于3 的数据位置是: 18行
由最小值恢复到80%平均值水平的时间差为: 5秒

 w123456 回复于:2005-06-13 19:49:52
begincwcw  你的代码好C,呵呵

 begincwcw 回复于:2005-06-13 19:57:43
习惯了,w123456,我觉得你的问题很有针对性,我比较感兴趣。

 waker 回复于:2005-06-14 09:30:27
[code:1:087de50c90]awk 'BEGIN{min=1000}
{ a[$2]=a[$2]" "NR;sum+=$2; if ($2<min) {min=$2;minline=NR}}
END{ avg=sum/NR*0.8;sub(/\..*/,"",avg)
for (;!a[avg];avg++);
n=split(a[avg],b)
for (j=1;j<=n;j++){if (b[j]>minline) {print "min: "min
print "offset: "b[j]-minline"s";exit}}}' filename
[/code:1:087de50c90]

尝试扫描一次 :mrgreen:

 begincwcw 回复于:2005-06-14 13:14:46
waker,我觉得你的程序中,avg取整数的话有问题,如:平均数为6.28,第二十行为7的话没问题,但二十行为6的话,你的程序就有问题,就少一秒了。你可以试试?

 wayy2008 回复于:2005-06-14 13:22:07
找最小值,试一下这个:
sort -k2 filename|head -1
位置嘛,就比较麻烦一点了,呵呵。

 waker 回复于:2005-06-14 13:28:11
[quote:f702c8a960="begincwcw"]waker,我觉得你的程序中,avg取整数的话有问题,如:平均数为6.28,第二十行为7的话没问题,但二十行为6的话,你的程序就有问题,就少一秒了。你可以试试?[/quote:f702c8a960]

那就改改,avg+1 是不是就行了? :mrgreen:

[code:1:f702c8a960]
awk 'BEGIN{min=1000}
{ a[$2]=a[$2]" "NR;sum+=$2; if ($2<min) {min=$2;minline=NR}}
END{ avg=sum/NR*0.8;sub(/\..*/,"",avg)
for (;!a[++avg];);
n=split(a[avg],b)
for (j=1;j<=n;j++){if (b[j]>minline) {print "min: "min
print "offset: "b[j]-minline"s";exit}}}' filename [/code:1:f702c8a960]

 begincwcw 回复于:2005-06-14 13:45:43
[quote:dea97a806e="waker"]那就改改,avg+1 是不是就行了?[/quote:dea97a806e]

如果平均数是:5.82呢?

 waker 回复于:2005-06-14 14:18:39
5.82和5.02有什么区别?

 waker 回复于:2005-06-14 14:27:31
问题会出在avg正好是整数的时候,如果一行的值正好是平均值的80%时要不要计算在内,如果要

在 sub(....)前加一句 if(avg ~/\./)avg++好了

[code:1:3382bd3db4]
awk 'BEGIN{min=1000}
{ a[$2]=a[$2]" "NR;sum+=$2; if ($2<min) {min=$2;minline=NR}}
END{ avg=sum/NR*0.8;if(avg ~/\./)avg++;sub(/\..*/,"",avg)
for (;!a[avg];avg++);
n=split(a[avg],b)
for (j=1;j<=n;j++){if (b[j]>minline) {print "min: "min
print "offset: "b[j]-minline"s";exit}}}' filename 
[/code:1:3382bd3db4]

 begincwcw 回复于:2005-06-14 16:47:06
[quote:4509b98e93="awk 'BEGIN{min=1000} 
{ a[$2]=a[$2]" "NR;sum+=$2; if ($2<min) {min=$2;minline=NR}} 
END{ avg=sum/NR*0.8;if(avg ~/\./)avg++;sub(/\..*/,"",avg) 
for (;!a[avg];avg++); 
n=split(a[avg],b) 
for (j=1;j<=n;j++){if (b[j]>minline) {print "min: "min 
print "offset: "b[j]-minline"s";exit}}}' filename 
"][/quote:4509b98e93]

waker,我用你的程序测试了一下,测试结果如下:
cat filename
1 11 
2 9 
3 10 
4 11 
5 10 
6 9 
7 11 
8 10 
9 11 
10 10 
11 8 
12 7 
13 5 
14 3 
15 0 
16 2 
17 3 
18 6 
19 8 
20 9 
21 11 
22 12 
23 13 
24 10 
25 11 

平均值:6.72
最小值为: 0
第一个比最小值大于3 的数据位置是: 18行
由最小值恢复到80%平均值水平的时间差为: 4秒 

就用你上面的程序运行,但你的程序什么也没有显示。

cat filename
1 11 
2 9 
3 10 
4 11 
5 10 
6 9 
7 11 
8 10 
9 11 
10 10 
11 8 
12 7 
13 5 
14 3 
15 0 
16 1 
17 2 
18 4 
19 5 
20 7 
21 8 
22 10 
23 11 
24 10 
25 11 

平均值:6.208
最小值为: 0
第一个比最小值大于3 的数据位置是: 18行
由最小值恢复到80%平均值水平的时间差为: 5秒 

你的程序运行正确。
运行结果如下:
min: 0
offset: 5s

以上程序在unix5.0.5下测试,你可以去试试。

 waker 回复于:2005-06-14 21:02:48
awk 'BEGIN{min=1000}
{ a[$2]=a[$2]" "NR;sum+=$2; if ($2<min) {min=$2;minline=NR}}
END{ avg=sum/NR*0.8;[color=red:e6a1a89ea2]if(!avg ~/\./)avg++;[/color:e6a1a89ea2]sub(/\..*/,"",avg)
for (;!a[avg];avg++);
n=split(a[avg],b)
for (j=1;j<=n;j++){if (b[j]>minline) {print "min: "min
print "offset: "b[j]-minline"s";exit}}}' filename 


逻辑错误  :mrgreen:  纠正一下,多谢指正

 waker 回复于:2005-06-15 08:30:37
是我的方法有问题,如果合适的值在min之前出现就会有问题

 waker 回复于:2005-06-15 09:09:21
改一下
[code:1:7c25b947ce]
awk 'BEGIN {min=10000}
{ sum+=$2; if ($2<min) {min=$2;minline=NR;delete a}a[$2]=NR}
END{  avg=sum/NR*0.8;
if(sub(/\..*/,"",avg)) avg++;
for (;!a[avg];avg++);
print "min: "min
print "offset: "a[avg]-minline"s"}' filename

[/code:1:7c25b947ce]

 begincwcw 回复于:2005-06-15 11:23:11
waker可能我的awk版本与你的版本不一样,运行时提示delete a错误。

 waker 回复于:2005-06-15 12:33:36
`delete array ' 是gawk扩展
其它的版本可能是
for (i  in array) delete array[i]的形式

 begincwcw 回复于:2005-06-15 14:03:47
[quote:e627d27e73="waker"]delete array ' 是gawk扩展 
其它的版本可能是 
for (i  in array) delete array[i]的形式[/quote:e627d27e73]


多谢waker。

原文转自:http://www.ltesting.net