Solved Using bc for summation

balanga

Daemon

Reaction score: 101
Messages: 2,438

Does anyone know how to use bc() for summation of a file containing lines of numerical data such as?
Code:
123
456
33
46
 

obsigna

Aspiring Daemon

Reaction score: 490
Messages: 860

Why using bc(1) when sh(1) offers basic arithmetic by its own?
Code:
#!/bin/sh
for value in `cat table.txt`; do
   sum=$(($sum + $value))
done
echo $sum
Given your numbers stored into the file table.txt and let above script iterate over it → 658
 

jpierri

Member

Reaction score: 20
Messages: 55

If your list of numbers is on datafile.txt, one number per line, perhaps this is what you have been looking for:

$ echo -e "`cat datafile.txt | tr '\n' '+' | sed -e 's/+$//g;'`\n" | bc
658
 

ralphbsz

Daemon

Reaction score: 869
Messages: 1,410

My favorite answer:
Code:
cat datafile.txt | awk '
{ total += $1 }
END { print total }'
The thing between quotes is a 2-line awk program. The first line takes an arbitrary input line, and adds the first field in it to total. The second line is run after the last input line, and prints the total.
 
OP
OP
B

balanga

Daemon

Reaction score: 101
Messages: 2,438

If your list of numbers is on datafile.txt, one number per line, perhaps this is what you have been looking for:

$ echo -e "`cat datafile.txt | tr '\n' '+' | sed -e 's/+$//g;'`\n" | bc
658
That's the sort of command line I appreciate :).

Unfortunately I can't get it to work, but will keep trying.
 
OP
OP
B

balanga

Daemon

Reaction score: 101
Messages: 2,438

My favorite answer:
Code:
cat datafile.txt | awk '
{ total += $1 }
END { print total }'
The thing between quotes is a 2-line awk program. The first line takes an arbitrary input line, and adds the first field in it to total. The second line is run after the last input line, and prints the total.
It looks simple enough, but do you need to change it when dealing with currency values (eg 5,200.00)?
 

sko

Well-Known Member

Reaction score: 218
Messages: 429

It looks simple enough, but do you need to change it when dealing with currency values (eg 5,200.00)?
To avoid any weird behaviour, I'd just convert them into a proper decimal notation (i.e. remove the commas):
Code:
awk '{ gsub(",", ""); total +=$1 } END { printf "%.2f\n", total }' input.txt
Of course this only works if your locale actually uses dot as decimal separator; or more generally: the input file has to use the same decimal separator as your locale...
 

jpierri

Member

Reaction score: 20
Messages: 55

That's the sort of command line I appreciate :).

Unfortunately I can't get it to work, but will keep trying.
Hmmm ... It is odd !
Please check this two things:
  1. Be sure to try it under /bin/sh (since /bin/csh may be your default shell)
  2. Be sure to use the backtick (`) instead of the single quote (') or else those commands will not be executed
 

ralphbsz

Daemon

Reaction score: 869
Messages: 1,410

In theory, if your locale is set correctly, the printing and scanning functions for number should all input and output currency format. So if you take "$5,200.00" and read it into an appropriate variable (an awk of python number, which is by default a floating point, or use C's scanf with an appropriate format), it should just work. In theory, there should be no need to use string substitution to remove the commas first.

In practice, internationalization and localization, in particular where currency values are concerned, is halfway between a disaster and a minefield. And since the automatic mechanisms don't work half the time, people get into the bad habit of doing it by hand.
 
OP
OP
B

balanga

Daemon

Reaction score: 101
Messages: 2,438

Hmmm ... It is odd !
Please check this two things:
  1. Be sure to try it under /bin/sh (since /bin/csh may be your default shell)
  2. Be sure to use the backtick (`) instead of the single quote (') or else those commands will not be executed
The problem seems to be with currency ie ',' and '.' . It does work with simple numbers.

And many thanks for showing me how to use bc() for simple calculation, which was the main aim of the thread.
 
Top