Hi i am trying to comapre numbers for the biggest among double type of numbers. For example: 0.254, 0.255, 0.564, 0.984, 0.556, 0.6566, and 0.5666.
I’m using the following script code:
if [ $max -lt $i ]
if [ “$max -lt “$i” ]
But they all give the error message “integer expression expected”. Help!
The shell is doing exactly what it should be doing, believe it or not. Shell scripts can’t really do proper mathematics, just piddly little simple integer math. So when you give it a number like 0.245 it sees “0” and some gobbledygook that it can’t figure out, hence the error message.
There are two ways you can solve this. The first is to actually use some sort of more sophisticated mathematical tool like bc to push out the conditional expression, then test its return value to see if your condition was met or not. That’s a bit tricky, particularly since bc can be difficult to use.
Instead, if indeed your input is always 0.something then I suggest that you can exploit that and simply strip off the “0.” prefix, then compare them as integers and get exactly the result you seek.
Here’s how I’d solve that:
max=0
while read value
do
val=”$(echo $value | sed ‘s/0.//’)”
if [ $val -gt $max ]
then
max=$val
fi
done
echo “max value is 0.$max”
exit 0
That should do what you seek as long as your input is always well-formed. Really, if this is going to be something that gets a lot of use, I’d probably also add some code that checks to ensure that the inputs all start with “0.” to be sure it never breaks too.
how do we compare the max 5 number useing with the while loop in shell programming?????
Hey, I’ve just done the following using expr (found on another website):
result=`expr $val1 \> $val2`
if [ “$result” -eq “1” ]; then
echo “$val1 is larger than $val2”
exit 0
fi
result=`expr $val2 \> $val1`
if [ “$result” -eq “1” ]; then
echo “$val2 is larger than $val1”
exit 0
fi
echo “the values are equal”
exit 0
I used this to replace the integer checks -gt, -lt, etc. :
# — calculate (T) —
echo “${time} = ${X}”
result=`expr ${time} \= ${X}`
if [ “$result” -eq “1” ] ;then
time=`echo “scale=2 ; 60 * ${dist}” | bc`
time=`echo “scale=2 ; ${time} / ${speed}” | bc`
fi
(basically if time var IS set to the initiated arbitrary value (e.g. 9999) then it needs to have a calculation on it.
Although the bash / bc solution would work fine, KSH is the way forward on this. Just declare your variables as floats with “typeset -F name=variable” and then continue with your calculations. It works a treat.
If you want to divide two real numbers using ‘bc’, you have to add the option ‘-l’ (load the math library). If not, sets the precision to zero (set scale=0) and do integer operations.
if you try ‘echo “5.2/1.2” | bc -l’ you’ll get what you expect.
Hi
I want to divide two real numbers which will give a real no too . But even after using |bc I am getting an integer.like 5.2/1.2 is given as 4 .
how can I fix this problem??
regards
sumanta
Hi, you can just do:
return_=`perl -e “if ( $cont > $cont10 ) { print 0; } else { print 1; }”`
and use $return to you next if:
if [ $return_ -eq 0 ] && [ $flag -eq 0 ]
then
bla bla bla
fi
Regards,
Breno BF
Thanks Justin, that short cut across comparing floating point numbers really helped me… doing that was such a torture…. however just for info is there an alternative way of doing it also … ?
Right, Shashank. You need to be a bit more tricky because the default setting for “bc” is to have zero digits after the decimal point. What you need to do is feed the statement “scale=2” or similar to get any precision at all. I explain it — with lots of examples — in my book Wicked Cool Shell Scripts, which you can learn about at http://www.intuitive.com/wicked/
How do I make complex floating operation in a linux script. If I try “100 / 500 | bc” it returns 0, instead of 0.20.
sorry for the above typo: please use this for Lowest value:
#To get Lowest value
echo 100 500 300 400 101 204 499|tr ‘ ‘ ‘\n’|sort|tail -n1
We can use tr+sort+head or tail to get high and low values
#To get Highest value
echo 100 500 300 400 101 204 499|tr ‘ ‘ ‘\n’|sort|head -n1
#To get Lowest value
echo 100 500 300 400 101 204 499|tr ‘ ‘ ‘\n’|sort|head -n1
#To see for yourself
echo 100 500 300 400 101 204 499|tr ‘ ‘ ‘\n’|sort
sir,
i have question to ask…
how do we compare the decimal values with the integer values in shell programming?????
and
how to find the maximum values among the no.s????
please give the answer with one or two examples.
The korn shell ( open source from at&t research ) has had
floating point arithmetic since 1993. So the original test
would become:
if (( max < i )); then … ; fi
On the other hand, I would not use ‘i’ for a floating point
variable, as single character variables like ‘i’ .. ‘n’ are by
convention used for integers in mathematics.
Plug: ksh93 gets shipped with some versions of unix and linux. Source and binaries can be found at at&t via kornshell.com.
Henk
a=1.2
b=2.3
echo $a|awk ‘{ if ($1 > ‘$b’) {print “a is bigger then b”}}’
use simply awk,like:
a=1.2
b=2.3
echo $a|awk ‘{ if ($1 < ‘$b’) {print “a is bigger then b”}}’
The one posted by Justin K is really a quick way of doing that, it helped me. Thanks Justin.
Hello. This might make a good interview question for a toolsmith SysAdmin. Here’s a script I wrote in answer. It includes flt and fgt functions, that use sort -n, as well as a test harness. Seems to work okay on this LINUX box:
#!/bin/sh
#
# “Floating Point” less-than or greater-than shell functions.
#
# Written as “proof-of-concept” answer for
# https://www.askdavetaylor.com/compare_float_real_numbers_in_a_shell_script.html
#
# Copyright 2007 Danny Howard, anyone can publish or reuse this code
# with attribution.
#
# Danny Howard
# http://dannyman.toldme.com/
function fgt () {
LHS=$1
RHS=$2
min=`(echo $LHS ; echo $RHS) | sort -n | head -1`
if [ “$min” = “$LHS” ]; then
return 1
else
return 0
fi
}
function flt () {
LHS=$1
RHS=$2
min=`(echo $LHS ; echo $RHS) | sort -n | head -1`
if [ “$min” = “$LHS” ]; then
return 0
else
return 1
fi
}
function true_or_false () {
FUNC=$1
ARG1=$2
ARG2=$3
echo -n “$FUNC $ARG1 $ARG2 … ”
$FUNC $ARG1 $ARG2
if [ $? -eq 0 ]; then
echo TRUE
else
echo FALSE
fi
}
true_or_false fgt 1.2 3.4
true_or_false flt 1.2 3.4
true_or_false fgt 0.9997 0.9996
When I run it:
> ./fgt.sh
fgt 1.2 3.4 … FALSE
flt 1.2 3.4 … TRUE
fgt 0.9997 0.9996 … TRUE
Dave perhaps you can re-insert the PRE tags. 😉
Cheers,
-danny
This question touches on a limitation of the Bash shell–namely, that it does not understand floating point arithmetic and treats such numbers as strings.
Bash documentation even goes on to say this:
“When not to use shell scripts
…
* Procedures involving heavy-duty math operations, especially floating point arithmetic, arbitrary precision calculations, or complex numbers (use C++ or FORTRAN instead)”
So the work-arounds are indirect and perhaps (for some) counter-intuitive. One simple way to fix your code in place is to pipe your input (presumably shell variables) to bc(1), an arbitrary precision calculator language.
An example follows below:
if [ $max -lt $i ]
becomes:
if [ $(echo “$max < $i”|bc) -eq 1 ]
Where you’re using a temporary subshell invocation to calculate and return a value for the test brackets. The comparison against 1 (“-eq 1”) is necessary.
This is the ‘quickest’ and smallest solution I can see to your problem, but I’m sure there are (better?) alternative methods. Hope that helps.
(sound of me slapping my head)
Doh! You’re absolutely right, Paul. I’ll dig into this and come up with a different solution, just for completion. 🙂
If you simply strip off the “0.”, then “0.984” will appear to be a smaller integer than “0.6566”, but if you compare the originals as strings (dictionary order), then the result would be correct. Unfortunately, neither of these approaches works when you have different numbers of digits before and after the decimal point. Then you’d have to “normalize” by adding leading or trailing zeroes depending on whether you want to use string comparison or integer comparison.