LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 06-24-2005, 10:24 AM   #1
abefroman
Senior Member
 
Registered: Feb 2004
Location: Chicago
Distribution: CentOS
Posts: 1,256

Rep: Reputation: 53
How can I compare floating number in a shell script?


root@server1 [/]# ./ss3
./ss3: [: 3.1: integer expression expected
root@server1 [/]# cat ss3
#!/bin/bash
X=3.1
Y=3.2
empty_string=""
if [ $X -lt $Y ] # is $X less than $Y ?
then
echo "\$X=${X}, which is greater than \$Y=${Y}"
fi

Why does it say integer expression expected? How can I compare floats?

===========================================
It wont even work in C shell
root@server1 [/]# ./ss3
if: Badly formed number.
root@server1 [/]# cat ss3
#! /bin/csh -f
set X=3.1
set Y=4.1
if ( $X < $Y ) then
echo "\$X=${X}, which is greater than \$Y=${Y}"
endif

Last edited by abefroman; 06-24-2005 at 10:30 AM.
 
Old 06-24-2005, 11:02 AM   #2
MoneyCat
LQ Newbie
 
Registered: Jun 2005
Location: USA
Distribution: Ubuntu 5.04
Posts: 10

Rep: Reputation: 0
Quote:
Why does it say integer expression expected? How can I compare floats?
This is because the -lt, -gt, -le, -ge, comparisons are only designed for integers. Try using these operators: >, <, >=, <=


Also there is a minor logic problem:
Code:
if [ $X -lt $Y ] # is $X less than $Y ?
then
echo "\$X=${X}, which is greater than \$Y=${Y}"
In the above code, you test if X is LESS THAN Y but then output X is GREATER THAN Y.


Good luck

Last edited by MoneyCat; 06-24-2005 at 11:13 AM.
 
Old 06-24-2005, 12:20 PM   #3
abefroman
Senior Member
 
Registered: Feb 2004
Location: Chicago
Distribution: CentOS
Posts: 1,256

Original Poster
Rep: Reputation: 53
It still wont work, got any tips?

root@server1 [/]# cat ss3
#! /bin/csh -f
set X=3.1
set Y=4.1
if [ $X < $Y ] then
echo "wassup"
endif

root@server1 [/]# ./ss3
4.1: No such file or directory.
root@server1 [/]# pico ss3
root@server1 [/]# ./ss3
if: Badly formed number.
root@server1 [/]# cat ss3
#! /bin/csh -f
set X=3.1
set Y=4.1
if ( "$X" < "$Y" ) then
echo "wassup"
endif
 
Old 06-24-2005, 12:36 PM   #4
abefroman
Senior Member
 
Registered: Feb 2004
Location: Chicago
Distribution: CentOS
Posts: 1,256

Original Poster
Rep: Reputation: 53
I tried it in perl but it doesnt store the right value to $a as it does in bash or cshell:
root@server1 [/]# cat ss4
#!/usr/bin/perl
$a=`uptime | awk -F'[, ]*' '{print $11}'`;
#echo "a = $a"
if ( $a > 5.2 ){
print $a;
}


root@server1 [/]# ./ss4
12:34pm up 29 days, 18:11, 1 user, load average: 0.43, 0.32, 0.33
 
Old 06-24-2005, 12:54 PM   #5
MoneyCat
LQ Newbie
 
Registered: Jun 2005
Location: USA
Distribution: Ubuntu 5.04
Posts: 10

Rep: Reputation: 0
This code below works:

Code:
      1 #!/bin/bash
      2 X=3.1
      3 Y=3.2
      4 empty_string=""
      5
      6 if [ $X < $Y ] # is $X less than $Y ?
      7 then
      8     echo "\$X=${X}, which is less than \$Y=${Y}"
      9 elif [ $X > $y ]
     10 then
     11     echo "\$X=${X}, which is greater than \$Y=${Y}"
     12 fi

Last edited by MoneyCat; 06-24-2005 at 12:55 PM.
 
Old 06-24-2005, 01:26 PM   #6
perfect_circle
Senior Member
 
Registered: Oct 2004
Location: Athens, Greece
Distribution: Slackware, arch
Posts: 1,783

Rep: Reputation: 52
Re: How can I compare floating number in a shell script?

Quote:
Originally posted by abefroman
root@server1 [/]# ./ss3
./ss3: [: 3.1: integer expression expected
root@server1 [/]# cat ss3
#!/bin/bash
X=3.1
Y=3.2
empty_string=""
if [ $X -lt $Y ] # is $X less than $Y ?
then
echo "\$X=${X}, which is greater than \$Y=${Y}"
fi

Why does it say integer expression expected? How can I compare floats?

===========================================
It wont even work in C shell
root@server1 [/]# ./ss3
if: Badly formed number.
root@server1 [/]# cat ss3
#! /bin/csh -f

set X=3.1
set Y=4.1
if ( $X < $Y ) then
echo "\$X=${X}, which is greater than \$Y=${Y}"
endif
As other people have already posted there are ways to work this out but in general case you should know this:
Quote:
Bash does not understand floating point arithmetic. It treats numbers containing a decimal point as strings.
Quote:
When not to use shell scripts

*

Resource-intensive tasks, especially where speed is a factor (sorting, hashing, etc.)
*

Procedures involving heavy-duty math operations, especially floating point arithmetic, arbitrary precision calculations, or complex numbers (use C++ or FORTRAN instead)
*

Cross-platform portability required (use C instead)
*

Complex applications, where structured programming is a necessity (need type-checking of variables, function prototypes, etc.)
*

Mission-critical applications upon which you are betting the ranch, or the future of the company
*

Situations where security is important, where you need to guarantee the integrity of your system and protect against intrusion, cracking, and vandalism
*

Project consists of subcomponents with interlocking dependencies
*

Extensive file operations required (Bash is limited to serial file access, and that only in a particularly clumsy and inefficient line-by-line fashion)
*

Need multi-dimensional arrays
*

Need data structures, such as linked lists or trees
*

Need to generate or manipulate graphics or GUIs
*

Need direct access to system hardware
*

Need port or socket I/O
*

Need to use libraries or interface with legacy code
*

Proprietary, closed-source applications (shell scripts put the source code right out in the open for all the world to see)

Last edited by perfect_circle; 06-24-2005 at 01:30 PM.
 
Old 06-24-2005, 01:37 PM   #7
sirclif
Member
 
Registered: Sep 2004
Location: south texas
Distribution: fedora core 3,4; gentoo
Posts: 192

Rep: Reputation: 30
yea, you can't do very much arithmetic in bash directly. you can pipe some commands to the calculator 'bc', and it will spit out the answer to the standard output.

> echo 3.14 + 5.16 | bc
8.30

as for a comparison, bc has some comparison capability, but you may be able to do something similar with a different tool, by piping it the comparison, and looking at what it returns.
 
Old 06-24-2005, 04:54 PM   #8
ahh
Member
 
Registered: May 2004
Location: UK
Distribution: Gentoo
Posts: 293

Rep: Reputation: 31
I think awk will do the job:-
Code:
ahh@desktop ~ $ x=3.1; y=3.2; echo "$x $y" | awk '{if ($1 > $2) print $1; else print $2}'
3.2
I'm sure you can adapt it to your script.
 
Old 08-07-2007, 09:48 AM   #9
wmjosiah
LQ Newbie
 
Registered: Aug 2007
Location: Winchester, NH
Distribution: ubuntu
Posts: 3

Rep: Reputation: 0
Actually, that doesn't work exactly. Even if you set X to 3.5, it will still say that X is less than Y.



Quote:
Originally Posted by MoneyCat
This code below works:

Code:
      1 #!/bin/bash
      2 X=3.1
      3 Y=3.2
      4 empty_string=""
      5
      6 if [ $X < $Y ] # is $X less than $Y ?
      7 then
      8     echo "\$X=${X}, which is less than \$Y=${Y}"
      9 elif [ $X > $y ]
     10 then
     11     echo "\$X=${X}, which is greater than \$Y=${Y}"
     12 fi
 
Old 08-07-2007, 06:25 PM   #10
chrism01
Guru
 
Registered: Aug 2004
Location: Sydney
Distribution: Centos 6.5, Centos 5.10
Posts: 16,261

Rep: Reputation: 2028Reputation: 2028Reputation: 2028Reputation: 2028Reputation: 2028Reputation: 2028Reputation: 2028Reputation: 2028Reputation: 2028Reputation: 2028Reputation: 2028
Another option in shell is to call expr for doing fp calcs.
I'm curious as to why you think Perl doesn't work, but then I noticed (commented out) 'echo', which is not a perl cmd/keyword.
Try
print "$a\n";

In fact, I'd just call uptime and then do the string parse in perl, instead of piping through awk.
 
Old 08-08-2007, 12:20 PM   #11
makyo
Member
 
Registered: Aug 2006
Location: Saint Paul, MN, USA
Distribution: {Free,Open}BSD, CentOS, Debian, Fedora, Solaris, SuSE
Posts: 718

Rep: Reputation: 72
Hi.

Some shells like zsh understand floating point. Here's a sample comparing bash and zsh. It writes a file t1, then asks bash and zsh to execute it:
Code:
#!/bin/sh

# @(#) s1       Compare bash and zsh for arithmetic.

set -o nounset

cat >t1 <<'EOF'

if [ -n "$BASH_VERSION" ]
then
  echo " From bash, version :$BASH_VERSION:"
elif [ -n "$ZSH_VERSION" ]
then
  echo " From zsh, version :$ZSH_VERSION:"
else
  echo " Unknown shell."
fi

float X Y
(( X = 3.0 + 0.5 ))
(( Y = 33.0 / 10.0 ))
if (( $X < $Y )) # is $X less than $Y ?
then
  echo "\$X=${X}, which is less than \$Y=${Y}"
elif (( $X > $Y ))
then
  echo "\$X=${X}, which is greater than \$Y=${Y}"
fi

EOF

echo
bash t1

echo
zsh t1

exit 0
Producing:
Code:
% ./s1

 From bash, version :2.05b.0(1)-release:
t1: line 12: float: command not found
t1: line 13: ((: X = 3.0 + 0.5 : syntax error in expression (error token is ".0+ 0.5 ")
t1: line 14: ((: Y = 33.0 / 10.0 : syntax error in expression (error token is ".0 / 10.0 ")
$X=3, which is less than $Y=33

 From zsh, version :4.2.4:
$X=3.500000000e+00, which is greater than $Y=3.300000000e+00
cheers, makyo
 
Old 09-12-2008, 04:28 AM   #12
vamsi.coe
LQ Newbie
 
Registered: Sep 2008
Posts: 1

Rep: Reputation: 0
Talking May be this will work...

this is a naive way to do this.. but it works


#!/bin/ksh

parm_num=$#

if [ $parm_num -ne 2 ]
then
echo "enter two parameters"
exit 1
fi

d=`echo $1 - $2|bc`
#echo $d
count=`echo $d |grep "-" |wc -l`
if [ $count > 0 ]
then
echo "$2 is greater than $1"
else
echo "$1 is greater than $2"
fi
 
Old 09-15-2008, 07:53 AM   #13
jchambers
Member
 
Registered: Aug 2007
Location: California
Distribution: Debian
Posts: 127

Rep: Reputation: 15
EDIT: I deleted the prior function as it was flawed...


This one is more complex but will work wit numbers that are not the same length.

It checks if input A is greater that input B.


Code:
#!/bin/sh


a=2.25
b=1.0035

function f_AgtB()
{
	a=$1
	b=$2
	if [ "${a}" != "" -a "${b}" != "" ]
	then
		len_a=${#a}
		len_b=${#b}
		
		if [ $len_a -gt $len_b ]
		then
			b=${b}`f_add_zeros $(( $len_a - $len_b ))`
		else
			a=${a}`f_add_zeros $(( $len_b - $len_a ))`
		fi
		
		a=`echo $a | sed 's/\.//'`
		b=`echo $b | sed 's/\.//'`
		
		if [ $a -gt $b ]
		then
			echo 1
		else
			echo 0
		fi
	fi
}


function f_add_zeros()
{
	i=0
	while [ $i -lt $1 ]
	do
		out=${out}0
		((i++))
	done
	echo $out
}



if [ `f_AgtB $a $b` == 1 ]
then
	echo "CORRECT"
else
	echo "WRONG"
fi


exit

You may want to add some error correction if there is no '.'

Jon

Last edited by jchambers; 09-18-2008 at 02:19 AM.
 
Old 03-26-2010, 04:41 AM   #14
ydrol
LQ Newbie
 
Registered: Oct 2005
Posts: 3

Rep: Reputation: 0
Just in case anyone is directed to this page, rather than doing some horribly convoluted solution, the following will work on most systems (even ones that dont have bc and perl) - eg many small devices running busybox.
As ahh said - 'awk' is probably your best friend here:

Code:
# Return the value of an operation
float_val() {
     echo | awk 'END { print '"$1"'; }'
}
Or more usefully
Code:
# Return status code of a comparison
float_test() {
     echo | awk 'END { exit ( !( '"$1"')); }'
}
Note you have to invert it as exit(0) = success.

Full Example:

Code:
$ cat q.sh
# Float comparison eg float '1.2 > 1.3'

# Return the value of an operation
float_val() {
     echo | awk 'END { print '"$1"'; }'
}

# Return status code of a comparison
float_test() {
     echo | awk 'END { exit ( !( '"$1"')); }'
}
##########################################

x=1.2
y=1.02
float_test "$x > $y" && echo "$x > $y"

float_test "$x < $y" && echo "$x < $y"

z=`float_val "$x + $y"`

echo "$x + $y = $z"

z=`float_val "$x - $y"`

echo "$x - $y = $z"
Output:

Code:
$ sh q.sh
1.2 > 1.02
1.2 + 1.02 = 2.22
1.2 - 1.02 = 0.18

Last edited by ydrol; 04-26-2010 at 09:06 AM.
 
Old 04-26-2010, 04:11 AM   #15
Galogen
LQ Newbie
 
Registered: Apr 2010
Posts: 1

Rep: Reputation: 0
compare_result=`echo "2.2 > 1.1" | bc`
if [ $compare_result ]; then
echo 1
fi

Last edited by Galogen; 04-27-2010 at 03:24 AM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
shell script problem, want to use shell script auto update IP~! singying304 Programming 4 11-29-2005 05:32 PM
How to compare records in two tables in seperate My Sql database using shell script sumitarun Programming 5 04-14-2005 09:45 AM
compare date uusing shell programming please... izza_azhar Programming 7 01-14-2005 07:24 AM
Need text pattern compare script kscott121 Linux - Software 4 05-10-2004 01:13 PM
Help with a Directory Compare Script bullfrog Linux - General 1 02-04-2003 08:05 AM


All times are GMT -5. The time now is 03:07 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration