Mam nazwę pliku liczby, po prostu zawierają pęczek liczb losowych
1 2 3
7 5 9
2 2 9
5 4 5
7 2 6
Muszę stworzyć skrypt, który znajdzie medianę dla każdego wiersza, a oto mój kod:
while read -a row
do
for i in "${row[@]}"
do
length=`expr ${#row[@]} % 2`
if [ $length -ne 0 ] ; then
mid=`expr ${#row[@]} / 2`
echo ${row[middle]}
elif [ $length -eq 0 ] ; then
val1=`expr ${#row[@]} / 2`
val2=`expr (${$row[@]} / 2) + 1`
mid=`expr ($val1 + $val2) / 2`
echo $mid
done | sort -n
done < numbers
Jednak to nie działa, zamiast tego pokazuje błąd, jaki błąd popełniłem w tym kodzie? Również nadal nie wiem, gdzie jest właściwy sposób umieszczenia sort -n
ponieważ musi najpierw zostać posortowane przed obliczeniem mediany, prawda?
Odpowiedzi:
1 dla odpowiedzi № 1Bash może wykonywać tylko arytmetykę całkowitą, potrzebujesz narzędzia takiego jak bc
obliczyć średnią:
#!/bin/bash
while read -a n ; do
n=($(IFS=$"n" ; echo "${n[*]}" | sort -n))
len=${#n[@]}
if (( len % 2 )) ; then
echo ${n[ len / 2 ]}
else
bc -l <<< "scale=1; (${n[ len / 2 - 1 ]} + ${n[ len / 2 ]}) / 2"
fi
done
Prawdopodobnie sięgnę do języka wyższego poziomu, np. Perl:
#!/usr/bin/perl
use warnings;
use strict;
while (<>) {
my @n = sort { $a <=> $b } split;
print @n % 2 ? $n[ @n / 2 ]
: ($n[ @n / 2 - 1 ] + $n[ @n / 2 ]) / 2,
"n";
}
0 dla odpowiedzi nr 2
Po prostu musiałem to zszokować, dla zabawy.
Zauważ, że nie używam if
ale ułamki indeksów.
awk "{
split($0,a) # create array a from input line
asort(a,b) # sort array into array b (gnu awk specific)
# add twice the median, or around the median and divide by 2
print ( b[int(NF/2+0.7)] + b[int(NF/2+1.2)] )/2
}" numbers
Skrócone (67 znaków):
awk "{split($0,a);asort(a,b);print(b[int(NF/2+0.7)]+b[int(NF/2+1.2)])/2}" numbers
66 znaków w golfa :-)
awk "{split($0,a);asort(a,b);$0=(b[int(NF/2+0.7)]+b[int(NF/2+1.2)])/2}1" numbers