script to compare two floating point numbers or expressions

script to compare two floating point numbers or expressions

I wonder how other people would approach this. I often have to compare
two values when writing scripts and one or both of these values might
be an expression. I wrote a script to do it but I can't help thinking
there might be a much easier way. I am assuming the bash shell.

#!/bin/bash
# Script     : compfl
# Version    : 1.0
# Author     : Roland Rashleigh-Berry
# Date       : 03-Nov-2004
# Purpose    : To compare two floating point numbers
# SubScripts : none
# Notes      : Will work with integers and also fractions and
expressions.
#              Returns GT, EQ or LT.
#              It will calculate fractions or expressions to 9 decimal
places
# Usage      : compfl  1.2  3.4
#              compfl 355/113 3.14159
#              compfl 3*1.33  3.99
#              if [ "\$(compfl 1.2 3.4)" == "LT" ] ; then
#                print "less than"
#              fi
#================================================================================
# PARAMETERS:
#-pos- -------------------------------description--------------------------------
#  1   First number (or expression) to compare
#  2   Second number (or expression) to compare
#================================================================================
# AMENDMENT HISTORY:
# init --date-- mod-id
----------------------description-------------------------
#
#================================================================================

if [ \$# -ne 2 ] ; then
echo "Usage: compfl  6.67  4.45" 1>&2
exit 1
fi

# recalculate just in case they are fractions or expressions
num1=\$(echo "scale=9; \$1 + 0" | bc -l)
num2=\$(echo "scale=9; \$2 + 0" | bc -l)

# compare within gawk
echo | gawk '{
if (num1 > num2)
print "GT"
else
{
if (num1 == num2)
print "EQ"
else
print "LT"
}

Quote:}' num1="\$num1" num2="\$num2"

script to compare two floating point numbers or expressions

2004-11-5, 06:49(-08), RolandRB:
Quote:> I wonder how other people would approach this. I often have to compare
> two values when writing scripts and one or both of these values might
> be an expression. I wrote a script to do it but I can't help thinking
> there might be a much easier way. I am assuming the bash shell.

[...]

given that a shell is not a tool to do mathmatics, I would
suggest you use octave, python or perl instead of a shell.

Now, some shells have floating point arithmetic support (ksh93,
zsh)

In zsh:

num1='3.14159265 * 4'
num2=13
(( num1 < num2 )) && echo "4*Pi < 13"

Or, you can use awk:

awk -vnum1="\$((num1))" -vnum2="\$((num2))" '
BEGIN{exit !(num1 < num2)}' && echo "4*Pi < 13"

--
Stephane

script to compare two floating point numbers or expressions

> I wonder how other people would approach this. I often have to compare
> two values when writing scripts and one or both of these values might
> be an expression. I wrote a script to do it but I can't help thinking
> there might be a much easier way. I am assuming the bash shell.

[snip]
> # recalculate just in case they are fractions or expressions
> num1=\$(echo "scale=9; \$1 + 0" | bc -l)
> num2=\$(echo "scale=9; \$2 + 0" | bc -l)

Why not let bc do it all in one call?

case \$( echo "scale=9; (\$1) - (\$2)" | bc -l ) in
0) echo EQ ;;
-*) echo LT ;;
*) echo GT ;;
esac

On the other hand, it can be done entirely with the shell. It
looks cumbersome, but once the functions are written, they can be
put away in a library. It doesn't handle expressions, but it
executes 5 to 20 times faster than the bc solution. Examples of
usage:

\$ _max2fp 1.2345 1.2354
\$ case \$? in 0) echo EQ ;; 1) echo GT ;; 2) echo LT ;; esac
LT
\$ max2fp 23.456 23.465
23.465
\$ _max2fp 23.46 23.54
\$ echo \$?
2
\$ echo \$_MAX2FP
23.54
\$ _max2fp 3.456 3.4560 && echo EQ || echo "NE; \$_MAX2FP is larger"
EQ

The functions:

max2fp()
{
_max2fp \$1 \$2
case \$? in
0|1) echo \$1 ;;
2) echo \$2 ;;
esac

Quote:}

_max2fp()
{
[ \$# = 2 ] || return 5
[ "\$1" = "\$2" ] && return

## split args into integer and fractional parts
case \$1 in
*.*) fp1=\${1#*.}
int1=\${1%.*}
dp1=\${#fp1}
;;
*) fp1=
int1=\$1
dp1=0
;;
esac
case \$2 in
*.*) fp2=\${2#*.}
int2=\${2%.*}
dp2=\${#fp2}
;;
*) fp2=
int2=\$2
dp2=0
;;
esac

## if the integer parts are not equal, return result
case \$((  \$int1 - \$int2 )) in
0)  ;;
-*) return 2 ;;
*)  return 1 ;;
esac

## make lengths of fractional parts even
while [ \${#fp1} -gt \${#fp2} ]
do
fp2=\${fp2}0
done
while [ \${#fp2} -gt \${#fp1} ]
do
fp1=\${fp1}0
done

while :
do
case \$fp1 in
0*) fp1=\${fp1#0} ;;
*) break ;;
esac
done
while :
do
case \$fp2 in
0*) fp2=\${fp2#0} ;;
*) break ;;
esac
done

## compare the difference
case \$(( \${fp1:-0} - \${fp2:-0} )) in
0) _MAX2FP=\$1
return 0 ;;
-*) _MAX2FP=\$2
return 2 ;;
*)  _MAX2FP=\$1
return 1 ;;
esac

Quote:}

_max2()
{
[ \$# = 2 ] || { _MAX2=3; return 3; }
case \$(( \$1 - \$2 )) in
0) _MAX2=\$1
return 0
;;
-*) _MAX2=\$2
return 2
;;
*) _MAX2=\$1
return 1
;;
esac

Quote:}

--
Chris F.A. Johnson                  http://cfaj.freeshell.org/shell
===================================================================
My code (if any) in this post is copyright 2004, Chris F.A. Johnson
and may be copied under the terms of the GNU General Public License

How to use "if" comand to compare two float data in C shell script.
thanks for inputs