LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Bash: Calculating in array and storing result in array (https://www.linuxquestions.org/questions/linux-newbie-8/bash-calculating-in-array-and-storing-result-in-array-847950/)

ghantauke 12-02-2010 10:41 AM

Bash: Calculating in array and storing result in array
 
I have an array called arrayini which stores numbers. I want to take log to the base 2 of each of the numbers in that array and put it in file called result. I've used the following code to do it.
Code:

size=${#arrayini[@]}

for ((i=0;i<size;i++))
do
echo "scale = 12; l(${arrayini[$i]})/l(2)" | bc -l
done >result

It works fine but its taking pretty long to calculate since I've got about 230,000 items in the array. So I decided to store the result into an array hoping that it'd be faster. I tried the following code. arrayresult is where I try and store the result. The code doesn't work because of the second last line.
Code:

unset arrayresult
size=${#arrayini[@]}

for ((i=0;i<size;i++))
do
arrayresult[$i]="scale = 12; l(${arrayini[$i]})/l(2)" | bc -l
done >FILE2

There is a syntax error clearly. Please help.

David the H. 12-02-2010 11:12 AM

You need to set it up as an embedded command.
Code:

arrayresult[$i]=$( echo "scale = 12; l(${arrayini[$i]})/l(2)" | bc -l )
This puts the output of the string into the array variable.

Edit: Also, don't you need to echo the string into bc?

By the way, you can output a list of an array's index numbers with ${!array[@]}. It can be convenient and more accurate when looping through all of an array's elements.
Code:

for i in ${!arrayini[@]}
do
arrayresult[$i]=$( echo "scale = 12; l(${arrayini[$i]})/l(2)" | bc -l )
done

Edit again: Directing the output to FILE2 is useless here, since there is no output from this loop. It just sets the array. You'd have to echo it separately. Try this after the loop:
Code:

printf "%s\n" ${arrayresult[@]} >FILE2

ghantauke 12-02-2010 11:17 AM

Quote:

Originally Posted by David the H. (Post 4178452)
You need to set it up as an embedded command.
Code:

arrayresult[$i]=$( "scale = 12; l(${arrayini[$i]})/l(2)" | bc -l )
This puts the output of the string into the array variable.

By the way, you can output a list of an array's index numbers with ${!array[@]}. It can be convenient and more accurate when looping through all of an array's elements.
Code:

for i in ${!arrayini[@]}
do
arrayresult[$i]=$( "scale = 12; l(${arrayini[$i]})/l(2)" | bc -l )
done >FILE2


Thanks for telling me about the ${!arrayini[@]} looping. And thanks for the great solution.

Guttorm 12-02-2010 11:17 AM

Hi

I think what takes most of the time is calling bc 230000 times. Why not call it once instead? Also l(2) can be computed once instead of 230000 times.

Code:

#!/bin/bash

for (( i=1 ; i<=230000 ; i++ )) ; do
  a[$i]=$i
done

size=${#a[@]}

(
echo "scale=12; d=l(2);"
for (( i=1 ; i<=$size ; i++ )) ; do
  echo "l(${a[$i]})/d;"
done
) | bc -l

Edit:
I'm slow, answers came while i was typing.

ghantauke 12-02-2010 11:27 AM

Nevermind.

David the H. 12-02-2010 11:42 AM

Quote:

Originally Posted by Guttorm (Post 4178464)
I'm slow, answers came while i was typing.

No problems there. I was focusing entirely on the syntax problems, because I have no clue as to the actual math. :confused: And actually, my "solution" is probably slower than the original code, because pretty much all of the same operations have to be done, and then some. Yours is probably much more efficient.

ghantauke 12-02-2010 12:28 PM

Quote:

Originally Posted by Guttorm (Post 4178464)
Hi

I think what takes most of the time is calling bc 230000 times. Why not call it once instead? Also l(2) can be computed once instead of 230000 times.

Code:

#!/bin/bash

for (( i=1 ; i<=230000 ; i++ )) ; do
  a[$i]=$i
done

size=${#a[@]}

(
echo "scale=12; d=l(2);"
for (( i=1 ; i<=$size ; i++ )) ; do
  echo "l(${a[$i]})/d;"
done
) | bc -l

Edit:
I'm slow, answers came while i was typing.

Holy Molly! You're absolutely right. Its like 20 times faster now. Thanks a lot :)


All times are GMT -5. The time now is 03:02 PM.