calculating endless columns

I have about 5000 columns of data that i need to convert all of it into pecentages. for shorter colums i have been using this code:
{print $1/($1+$2)*100,$2/($1+$2),$3/($3+$4)*100 .....}
but this is a teadious process... is there anyway to do it without having to write all of them out?

sample data:
55 65 48 45 48 68 32 68 44 34 88 65
82 63 52 54 51 68 75 0 0 20 10 77
55 77 60 55 22 60 40 25 75 55 45 90
20 80 33 63 0 64 32 22 75 0 43 56
54 54 12 35 48 87 65 12 77 85 0 15

Output data:
45.83 54.16 51.61 48.38 .................... (all the columns are in pairs..$1 and $2 are a pair.. so while calculating column 3 and 4.. it would be $3/$3+4 and $4/$3+$4 .....$5/$5+$6, $6/($5,$6)

PS: there will be lines that will have to be divided by zero. in those cases i am using this code.. is it right? need to embedd it into the overall code as well..
if ($0 != 0) lines++; print 0

Thank you.:slight_smile:

Does it matter to keep the stuff on the originating line?
I am imagining a solution would would create a long list...

ya i can go on putting the code till those endless colums.. but that would take long and prone to errors..well... doesnt matter where it is.. as long as it works

Command instructions
I break up pairs of numbers, and put a ~ marker
get rid of new-line (carriage returns)
replace the ~ after each pair with a new-line; putting pairs on own rows
then do the awk command

> cat file30 | sed "s/[0-9]*.[0-9]*/&~/g" | tr "\n" " " | tr "~" "\n" | awk '$1*$2>0,z=$1+$2;x=$1/z;y=$2/z {print x,y}'

First couple enty outputs
it is repeating my inputs twice, & not sure why yet (still thinking about that)
then appears to be doing your % as requested

55 65
55 65
0.458333 0.541667
 48 45
 48 45
0.516129 0.483871

Perhaps this can get you started?
The awk needs to be 'finished'.

Also, the awk might be able to be augmented to use ~ as the RS (record separator). I just had issues trying to get that to work quickly.

hmm.. wat if the output should come out as per the input.. like corresponding to the output.?

anyone??

FORUM RULES...
(4) Do not 'bump up' questions if they are not answered promptly. No duplicate or cross-posting and do not report a post or send a private message where your goal is to get an answer more quickly.

There are many who try to answer here, but it is always on an "as possible" basis. Sometimes it might take a few days to get to a good answer -- all depends on when people have a chance to read through questions.

Somehow I cannot understand the algorithm, you said:

$1/($1+$2)*100,$2/($1+$2),$3/($3+$4)*100

Then you said:

$4/$3+$4 .....$5/$5+$6, $6/($5,$6)

What's ($5,$6)?

Hi,
The following code could be utilized. Its mostly built upon what has been posted above (by joeyg). A little bit of playing around with that could've helped.

cat file | sed "s/[0-9]*.[0-9]*/&~/g" | tr "~" "\n" | sed 's/$/ ;/g' | awk '{if ($0 != " ;" ) {print $1/($1+$2)","$2/($1+$2)";"} else {print "|";}}' | tr -d "\n" | tr "|" "\n" | sed 's/;/,/g;s/,$//g'

5000 columns will probably exceed your max input line. But if it fits, this ksh solution should work...

$ cat sample
55 65 48 45 48 68 32 68 44 34 88 65
82 63 52 54 51 68 75 0 0 20 10 77
55 77 60 55 22 60 40 25 75 55 45 90
20 80 33 63 0 64 32 22 75 0 43 56
54 54 12 35 48 87 65 12 77 85 0 15
$
$
$ cat calc
#! /usr/bin/ksh

bc |&
print -p scale=2
exec < sample
while read line ; do
       set -- $line
       while (($#)) ; do
               if (($1 + $2)) ; then
                       print -p "$1 * 100 / ($1 + $2)"
                       read -p result1
                       print -p "$2 * 100 / ($1 + $2)"
                       read -p result2
                       echo $result1 $result2 \\c
                       shift 2
               else
                       echo 00.00 00.00 \\c
               fi
       done
       echo
done
exit 0
$
$
$ ./calc
45.83 54.16 51.61 48.38 41.37 58.62 32.00 68.00 56.41 43.58 57.51 42.48
56.55 43.44 49.05 50.94 42.85 57.14 100.00 0 0 100.00 11.49 88.50
41.66 58.33 52.17 47.82 26.82 73.17 61.53 38.46 57.69 42.30 33.33 66.66
20.00 80.00 34.37 65.62 0 100.00 59.25 40.74 100.00 0 43.43 56.56
50.00 50.00 25.53 74.46 35.55 64.44 84.41 15.58 47.53 52.46 0 100.00
$

Thank you soooo much... really appreciate it..

Hey i have another query . I am trying to add all odd and even columns of the percentages calculated and adding them as columns to the left of the percentages.
so in the above percenages calculated totoal odd would be ($1+$3....= 45.83+51.61...) same thing for even as well

sample output:
t(odd) T(even)
313.28 315.22 45.83 54.16 51.61 48.38 41.37 58.62 32.00 68.00 ......
259.94 380.98 56.55 43.44 49.05 50.94 42.85 57.14 100.00 0

I was trying to embedd the add columns code in the ksh code.. somehow it is not working... and not able to output it as the collumns..

while read line ; do
set -- $line
while (($#)) ; do
if (($1 + $2)) ; then
print -p "$1 * 100 / ($1 + $2)"
read -p result1
print -p "$2 * 100 / ($1 + $2)"
read -p result2
echo $result1 $result2 \\c
shift 2
else
echo 00.00 00.00 \\c
fi
if (($1 +$3)); then
print -p "$1+$3"
read -p addodd
print -p "$2+$4"
read -p addeven
echo addodd addeven
done
echo
done

PS: not too familiar with ksh.. but i think it can be done with ksh

Thank you

can we use an arrary like this ???

array[i][j]
for (i = o,i <2000;,i++)
print i+2
for (j =1; j<2000)
print j+2

You need to buy a book on shell programming and come up to speed on this stuff. I'm not going to write all of your scripts for you. But here is this one...

$
$ cat calc
#! /usr/bin/ksh

bc |&
print -p scale=2
exec < sample
while read line ; do
       set -- $line
       output=""
       odd=0.00
       even=0.00
       while (($#)) ; do
               if (($1 + $2)) ; then
                       print -p "$1 * 100 / ($1 + $2)"
                       read -p result1
                       print -p "$2 * 100 / ($1 + $2)"
                       read -p result2
                       output="${output}$(echo $result1 $result2 \\c)"
                       print -p $odd + $result1
                       read -p odd
                       print -p $even + $result2
                       read -p even
                       shift 2
               else
                       output="${output}$(echo 00.00 00.00 \\c)"
               fi
       done
       echo $odd $even "${output}"
done
exit 0
$ ./calc
284.73 315.22 45.83 54.16 51.61 48.38 41.37 58.62 32.00 68.00 56.41 43.58 57.51 42.48
259.94 340.02 56.55 43.44 49.05 50.94 42.85 57.14 100.00 0 0 100.00 11.49 88.50
273.20 326.74 41.66 58.33 52.17 47.82 26.82 73.17 61.53 38.46 57.69 42.30 33.33 66.66
257.05 342.92 20.00 80.00 34.37 65.62 0 100.00 59.25 40.74 100.00 0 43.43 56.56
243.02 356.94 50.00 50.00 25.53 74.46 35.55 64.44 84.41 15.58 47.53 52.46 0 100.00
$

Thank you soo much. I do intend to buy a book on it..

since the total of odd and even column have become $1 and $2 respectively, i tried to do few substitions to divide the $3/$1 and $4/$2 ...$5/$1, $6/$2...but i seem to run into shift problems.

$
$ cat calc
#! /usr/bin/ksh
bc |&
print -p scale=2
exec < sample
while read line ; do
set -- $line
output=""
while (($#)) ; do
if (($3 / $1)) ; then
print -p "$3/$1)"
read -p result1
print -p "$4 / $2)"
read -p result2
output="${output}$(echo $result1 $result2//c"
shift 2
else
output="${output}$(echo 00.00 00.00 [\\c](file://\\c))"
fi
done
echo
done
exit 0
$ ./calc

PS: help one last time. .pleasee...:slight_smile:

In the code you set odd and even as 0.00..
does it mean that the variables are preset to 2 decimal places???
what is it doing ???

I really have no idea what you're talking about. The script does what you asked... just cut and paste it.

The input data is considered two columns at a time and they are $1 and $2. The "shift 2" makes the current $1 and $2 vanish. Then what used to be $3 and $4 become the new $1 and $2. The odd and even column is $odd and $even. They must get reset to zero for each line of input. And normally echo would output lines including a newline character at the end. You don't want two numbers per line so we need to surpress that newline character and \\c does that. We need to store the calculated %'s in output, because we won't have a finished even and odd until we finish with the line.

okk.. understood the description... i did copy and paste the code... but i i had to divide the even columns by the sum of even columns and odd by sum of odd columns.. $3/$1, $4/$2,$5/$1,$6/$2......would the code in red be right??

if (($3 + $4)) ; then
print -p "$3 * 100 / ($1)"
read -p result3
print -p "$4 * 100 / ($2)"
read -p result4#
echo $result3 $result4 \\c
shift 2
else
echo 00.00 00.00 \\c

Well I finally understand that "endless" in the title.

I don't see anything in red. But you're not very close. It's wrong to keep trying to use $3 and $4. The totals are calculated during the loop. Until the loop finishes, there no totals available. You will need a second loop to reprocess the data after the totals have been found.

Had you given the real requirements on the weekend I could have written the script you needed instead of one you can't use. :frowning: I don't have time now. Maybe someone else can write the next couple of versions for you.

awk '{
for(i=1;i<=NF;i++)
{ if(i%2)
printf("%.2f ",$i100/($i+$(i+1)))
else
printf("%.2f ",$i
100/($i+$(i-1)))
}
print ""
}' filename