Bash Multiplying Decimal to int - bash

I read price from user input. When i multiply the input with int like this
T="$((PRICE*QTY))"|bc; gives
line 272: 12.00: syntax error: invalid arithmetic operator (error token is ".00")
or .50
depending on user input. How do i multiply these two variables and get a total with 2 decimal points?

this works:
PRICE=1.1
QTY=21
RES=$(echo "scale=4; $PRICE*$QTY" | bc)
echo $RES

var=$(echo "scale=2;$PRICE*$QTY" |bc)
You can also use awk
awk -vp=$PRICE -vq=$QTY 'BEGIN{printf "%.2f" ,p * q}'

T="$(echo "$PRICE*$QTY" | bc)"

You can use
mul=0.8
exp=200
texp=awk -vp=$mul -vq=$exp 'BEGIN{printf "%.2f" ,p * q}'
Hope this is going to work.

First, trying to do floating-point arithmetic with bc(1) without using the -l flag is bound to give you some funny answers:
sarnold#haig:~$ bc -q
3.5 * 3.5
12.2
sarnold#haig:~$ bc -q -l
3.5 * 3.5
12.25
Second, the $((...)) is an attempt to do arithmetic in your shell; neither my bash nor dash can handle floating point numbers.
If you want to do the arithmetic in your shell, note printf(1) as well as (probably) your shell's built-in printf function. If you want to do the arithmetic in bc, note the special variable scale.

Related

Bash Error when echo print two number variables [duplicate]

echo 3+3
How can I evaluate such expressions in Bash, in this case to 6?
echo $(( 3+3 ))
expr is the standard way, but it only handles integers.
bash has a couple of extensions, which only handle integers as well:
$((3+3)) returns 6
((3+3)) used in conditionals, returns 0 for true (non-zero) and 1 for false
let 3+3 same as (( ))
let and (( )) can be used to assign values, e.g.
let a=3+3
((a=3+3))
for floating point you can use bc
echo 3+3 | bc
in shells such as zsh/ksh, you can use floats for maths. If you need more maths power, use tools like bc/awk/dc
eg
var=$(echo "scale=2;3.4+43.1" | bc)
var=$(awk 'BEGIN{print 3.4*43.1}')
looking at what you are trying to do
awk '{printf "%.2f\n",$0/59.5}' ball_dropping_times >bull_velocities
You can make use of the expr command as:
expr 3 + 3
To store the result into a variable you can do:
sum=$(expr 3 + 3)
or
sum=`expr 3 + 3`
Lots of ways - most portable is to use the expr command:
expr 3 + 3
I believe the ((3+3)) method is the most rapid as it's interpreted by the shell rather than an external binary.
time a large loop using all suggested methods for the most efficient.
Solved thanks to Dennis, an example of BC-use:
$ cat calc_velo.sh
#!/bin/bash
for i in `cat ball_dropping_times`
do
echo "scale=20; $i / 59.5" | bc
done > ball_velocities
My understanding of math processing involves floating point processing.
Using bashj (https://sourceforge.net/projects/bashj/) you can call a java method (with floating point processing, cos(), sin(), log(), exp()...) using simply
bashj +eval "3+3"
bashj +eval "3.5*5.5"
or in a bashj script, java calls of this kind:
#!/usr/bin/bashj
EXPR="3.0*6.0"
echo $EXPR "=" u.doubleEval($EXPR)
FUNCTIONX="3*x*x+cos(x)+1"
X=3.0
FX=u.doubleEval($FUNCTIONX,$X)
echo "x="$X " => f(x)=" $FUNCTIONX "=" $FX
Note the interesting speed : ~ 10 msec per call (the answer is provided by a JVM server).
Note also that u.doubleEval(1/2) will provide 0.5 (floating point) instead of 0 (integer)
One use case that might be useful in this regard is, if one of your operand itself is a bash command then try this.
echo $(( `date +%s\`+10 )) or even echo $(( `date +%s\`+(60*60) ))
In my case I was trying to get Unixtime 10 seconds and hour later than current time respectively.

addition in bash with decimal using bc

I'm new in bash and i'd like to know why my script doesn t work the way i'd like it work..
I have this bash script:
#!/bin/bash
read n
var=($(cat))
bim=${var[*]}
toto=$(echo $bim | sed 's/ /+/g' | bc)
echo $toto
bobo=$(($toto/$n | bc -l))
echo $bobo | awk '{printf "%.3f\n", $1}'
This is supposed to add up all the values that "cat" has stored in an array and divide the total by the first value that "read" reads. And the result should return me a decimal value of three decimal places. However, it only returns a round number to me when I use bc -l! And when I use awk '{printf% .3f ", $ 1}' it prints .000!
Do you know why?
Thanks
bash only does integer arithmetics and the arithmetic expansion
bobo=$(($toto/$n | bc -l))
will not do what you think. The pipe sign in | bc -l is not a pipe sign. It's a bitwise OR. Broken down:
$toto is interpreted as a variable (as would toto)
$n is interpreted as a variable (as would n)
| is bitwise OR
bc is interpreted as a variable (with the value 0)
- is interpreted as a minus sign (in an arithmetic expression)
l is interpreted as a variable (with the value 0)
So, it becomes $toto/$n | 0 -0 which is the same as the integer division toto/n ($ is not needed for variables in arithmetic expansions).
You could instead use bc for the division too, but you need to set the scale in bc. Here's an example setting it to 3 before performing the division:
bobo=$(echo "scale=3;$toto/$n" | bc)
Note that you don't need to echo this through awk.
Just echo $bobo and you should get the result you want.
Example input:
3
11.3
9
8
Output after having applied the suggested changes:
28.3
9.433

Floating-point division in bash

I'm trying to convert whatever numbers the user inputs into 2 decimal places.
For instance
What is the total cost in cents? 2345
output: 23.45
this is the code i have so far
percentage=20 #cannot change numerical value must convert into 0.20
echo -n "What is the total cost? ";
read cost_in_cents
echo "scale 1; $cost_in_cents" | bc
I'm also going to be doing some multiplication with percentage, how can i also convert the percentage into a float (0.20)
awk to the rescue!
you can define your own floating point calculator with awk, e.g.
$ calc() { awk "BEGIN{ printf \"%.2f\n\", $* }"; }
now you can call
$ calc 43*20/100
which will return
8.60
Perhaps it's nostalgia for reverse polish notation desk calculators, but I'd use dc rather than bc here:
dc <<<"2 k $cost_in_cents 100 / p"
Output is, properly, a float (with two digits past the decimal point of precision).
The exact same code, with no changes whatsoever, will work to convert 20 to .20.
See BashFAQ #22 for a full discussion on floating-point math in bash.
Bash itself could not process floats.
It can, however, printf them:
$ printf 'value: %06.2f\n' 23.45
value: 023.45
So, you need an external program to do the math:
$ echo "scale=4;2345/100*20/100" | bc
4.6900
Or, equivalent:
$ bc <<<"scale=4;2345*20/10^4"
4.6900
Then, you can format the float with printf:
$ printf 'result: %06.2f\n' $(bc <<<"scale=4;2345*20/10^4")
result: 004.69
Or you can use a program that can process floats; like awk.
How about this:
read -p "What is the total cost? " input
percent=20
echo "scale=2; $input / 100 * $percent / 100" | bc
# input = 2345 , output = 4.69

Multiplication on command line terminal

I'm using a serial terminal to provide input into our lab experiment. I found that using
$ echo "5X5"
just returns a string of "5X5". Is there a command to execute a multiplication operation?
Yes, you can use bash's built-in Arithmetic Expansion $(( )) to do some simple maths
$ echo "$((5 * 5))"
25
Check the Shell Arithmetic section in the Bash Reference Manual for a complete list of operators.
For sake of completeness, as other pointed out, if you need arbitrary precision, bc or dc would be better.
For more advanced and precise math consider using bc(1).
echo "3 * 2.19" | bc -l
6.57
Internal Methods
Bash supports arithmetic expansion with $(( expression )). For example:
$ echo $(( 5 * 5 ))
25
External Methods
A number of utilities provide arithmetic, including bc and expr.
$ echo '5 * 5' | /usr/bin/bc
25
$ /usr/bin/expr 5 \* 5
25
The classical solution is:
expr 5 \* 5
expr will only work with integer operands. Another nice option is:
echo 5 5\*p | dc
dc can be made to work with non-integer operands.
A simple shell function (no sed needed) should do the trick of interpreting '5X5'
$ calc() { bc -l <<< ${*//[xX]/*}; }
$ calc 5X5
25
$ calc 5x5
25
$ calc '5*5'
25
I use this function which uses bc and thus supports floating point calculations:
c () {
local a
(( $# > 0 )) && a="$#" || read -r -p "calc: " a
bc -l <<< "$a"
}
Example:
$ c '5*5'
25
$ c 5/5
1.00000000000000000000
$ c 3.4/7.9
.43037974683544303797
Bash's arithmetic expansion doesn't support floats (but Korn shell and zsh do).
Example:
$ ksh -c 'echo "$((3.0 / 4))"'
0.75
I have a simple script I use for this:
me#mycomputer:~$ cat /usr/local/bin/c
#!/bin/sh
echo "$*" | sed 's/x/\*/g' | bc -l
It changes x to * since * is a special character in the shell. Use it as follows:
c 5x5
c 5-4.2 + 1
c '(5 + 5) * 30' (you still have to use quotes if the expression contains any parentheses).
If you like python and have an option to install a package, you can use this utility that I made.
# install pythonp
python -m pip install pythonp
pythonp "5*5"
25
pythonp "1 / (1+math.exp(0.5))"
0.3775406687981454
# define a custom function and pass it to another higher-order function
pythonp "n=10;functools.reduce(lambda x,y:x*y, range(1,n+1))"
3628800

Bash: evaluate a mathematical term?

echo 3+3
How can I evaluate such expressions in Bash, in this case to 6?
echo $(( 3+3 ))
expr is the standard way, but it only handles integers.
bash has a couple of extensions, which only handle integers as well:
$((3+3)) returns 6
((3+3)) used in conditionals, returns 0 for true (non-zero) and 1 for false
let 3+3 same as (( ))
let and (( )) can be used to assign values, e.g.
let a=3+3
((a=3+3))
for floating point you can use bc
echo 3+3 | bc
in shells such as zsh/ksh, you can use floats for maths. If you need more maths power, use tools like bc/awk/dc
eg
var=$(echo "scale=2;3.4+43.1" | bc)
var=$(awk 'BEGIN{print 3.4*43.1}')
looking at what you are trying to do
awk '{printf "%.2f\n",$0/59.5}' ball_dropping_times >bull_velocities
You can make use of the expr command as:
expr 3 + 3
To store the result into a variable you can do:
sum=$(expr 3 + 3)
or
sum=`expr 3 + 3`
Lots of ways - most portable is to use the expr command:
expr 3 + 3
I believe the ((3+3)) method is the most rapid as it's interpreted by the shell rather than an external binary.
time a large loop using all suggested methods for the most efficient.
Solved thanks to Dennis, an example of BC-use:
$ cat calc_velo.sh
#!/bin/bash
for i in `cat ball_dropping_times`
do
echo "scale=20; $i / 59.5" | bc
done > ball_velocities
My understanding of math processing involves floating point processing.
Using bashj (https://sourceforge.net/projects/bashj/) you can call a java method (with floating point processing, cos(), sin(), log(), exp()...) using simply
bashj +eval "3+3"
bashj +eval "3.5*5.5"
or in a bashj script, java calls of this kind:
#!/usr/bin/bashj
EXPR="3.0*6.0"
echo $EXPR "=" u.doubleEval($EXPR)
FUNCTIONX="3*x*x+cos(x)+1"
X=3.0
FX=u.doubleEval($FUNCTIONX,$X)
echo "x="$X " => f(x)=" $FUNCTIONX "=" $FX
Note the interesting speed : ~ 10 msec per call (the answer is provided by a JVM server).
Note also that u.doubleEval(1/2) will provide 0.5 (floating point) instead of 0 (integer)
One use case that might be useful in this regard is, if one of your operand itself is a bash command then try this.
echo $(( `date +%s\`+10 )) or even echo $(( `date +%s\`+(60*60) ))
In my case I was trying to get Unixtime 10 seconds and hour later than current time respectively.

Resources