Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Korn Arithmetic Question 3

Status
Not open for further replies.

SamDurai

Programmer
Aug 30, 2009
10
US
Simple arithmetic works but bit complex arthimetic fails of possible syntax error. How should I handle this in shell script
Code:
/tmp > 
/tmp > cat t.ksh
a=3
b=5
c=`expr $a \* $b`
echo c=$c

var1=4
var2=5
var3=11
var4=15

result=`expr 100 - (( ( $var1 + $var2 ) \* 100 ) / ( $var3 + $var4))`
/tmp > 
/tmp > 
/tmp > t.ksh
c=15
t.ksh[11]: 0403-057 Syntax error at line 1 : `(' is not expected.
/tmp > 
/tmp > 
/tmp >

Any suggestions please
 
Hi

Escape the characters indicated in the error message :
Code:
[navy]result[/navy][teal]=[/teal]`expr [purple]100[/purple] - [teal]\([/teal] [teal]\([/teal] [teal]\([/teal] [navy]$var1[/navy] [teal]+[/teal] [navy]$var2[/navy] [teal]\)[/teal] [teal]\*[/teal] [purple]100[/purple] [teal]\)[/teal] [teal]/[/teal] [teal]\([/teal] [navy]$var3[/navy] [teal]+[/teal] [navy]$var4[/navy] [teal]\)[/teal] [teal]\)[/teal]`
SamDurai said:
Any suggestions please
Use [tt]bc[/tt] :
Code:
[navy]result[/navy][teal]=[/teal]`echo [green][i]"100 - (( ( $var1 + $var2 ) * 100 ) / ( $var3 + $var4))"[/i][/green] [teal]|[/teal] bc`

Feherke.
 
Let ksh - [tt](( ))[/tt] or [tt]let[/tt] - do the math instead of [tt]expr[/tt] or [tt]bc[/tt]:

with [tt](( ))[/tt] construct you automatically hide the other brackets

[tt]$ var1=4
$ var2=5
$ var3=11
$ var4=15
$ ((result=100-(var1+var2)*100/(var3+var4)))
$ echo $result
66[/tt]

with [tt]let[/tt] keyword you need quotes to hide the brackets from the shell

[tt]$ let "result=100-(var1+var2)*100/(var3+var4)"
$ echo $result
66[/tt]

Also note that you don't need to 'dollarize' the variables with [tt]let[/tt] or [tt](( ))[/tt] - [tt]var1[/tt] instead of [tt][red]$[/red]var1[/tt]


HTH,

p5wizard
 
May I know why "let" is preferable rather than expr or bc to handle arithmetic ?
 
Hi

SamDurai said:
May I know why "let" is preferable rather than expr or bc to handle arithmetic ?
Code:
[blue]master #[/blue] type let expr bc
let is a shell builtin
expr is /usr/bin/expr
bc is /usr/bin/bc
That means, [tt]let[/tt] is interpreted by the current [tt]ksh[/tt] process, for [tt]expr[/tt] and [tt]bc[/tt] a child process has to be started.


Feherke.
 
You mean choose between this:

[tt]result=`expr 100 - \( \( \( $var1 + $var2 \) \* 100 \) / \( $var3 + $var4 \) \)`[/tt]

and this:

[tt](( result = 100 - (var1 + var2) * 100 / (var3 + var4) ))[/tt]

I put in spaces for clarification, but [tt]let[/tt] or [tt](( ))[/tt] doesn't really need them.

Aside from feherke's technical explanation, your choice entirely. Just know that, as long as it is integer arythmetic, ksh does as good a job as expr or bc. Probably faster too.

HTH,

p5wizard
 
Thanks for sharing valuable information. I greatly appreciate your help.

I have few more questions..
1. How to get results in two digit accurary (like 66.36 instead of just 66)
2. How to handle divide by zero. Is there any inbuilt function available for do I need to handle it?

Code:
PP :/home/cardmnt: cat t.ksh
var1=4.1
var2=5.9
var3=11.4
var4=15.9
let "result=100-((var1+var2)*100/(var3+var4))"
echo result=$result


var1=4.1
var2=5.9
var3=0
var4=0
let "result=(var1+var2)*100/(var3+var4)"
echo result=$result

PP :/home/cardmnt: ./t.ksh
result=66
./t.ksh[13]: result=(var1+var2)*100/(var3+var4): 0403-056 Cannot divide by zero.
result=0
PP :/home/cardmnt:
 
ksh only knows integers and as far as I know does not have a way to handle division by zero.

for N-digit accuracy arythmetic with real numbers, see other threads that have touched this subject. Just last week for instance: thread822-1566273

It pays to state your full problem in your original post. :-(

HTH,

p5wizard
 
Hi

SamDurai said:
How to get results in two digit accurary (like 66.36 instead of just 66)
For real numbers I always use [tt]bc[/tt] and set its internal variable [tt]scale[/tt] as needed :
Code:
[navy]result[/navy][teal]=[/teal]`echo [green][i]"[highlight]scale=2;[/highlight] 100-(($var1+$var2)*100/($var3+$var4))"[/i][/green] [teal]|[/teal] bc`
SamDurai said:
How to handle divide by zero. Is there any inbuilt function available for do I need to handle it?
Manually. For example in [tt]bc[/tt] you can have control structures :
Code:
[navy]result[/navy][teal]=[/teal]`echo [green][i]"[highlight]if ($var3+$var4)[/highlight] ($var1+$var2)*100/($var3+$var4) [highlight]else 0[/highlight]"[/i][/green] [teal]|[/teal] bc`

Feherke.
 
Thanks. But when I tried it fails. Any thoughts ?

Code:
/tmp > cat t.ksh

var1=4.1
var2=5.9
var3=11.4
var4=15.9

result=`echo "scale=2; if ($var3+$var4) 100-(($var1+$var2)*100/($var3+$var4)) else 0" | bc`
echo result=$result
/tmp > t.ksh
syntax error on line 1 stdin
result=
/tmp >
 
Seems like the else clause must be a GNU extension.

The only way I could simulate it was with something horrible like this:

Code:
result=`echo "scale=2; if ($var3+$var4) 100-(($var1+$var2)*100/($var3+$var4)); i
f (($var3+$var4)==0) 0" | bc`

Annihilannic.
 
This is slightly less horrible:

Code:
result=`echo "scale=2; r=0; if ($var3+$var4) 100-(($var1+$var2)*100/($var3+$var4)); r" | bc`


Annihilannic.
 
This works but may I know what is the significance of "r=0 and r at the end".
Is it a temporary variable ?
How is it called technically in UNIX term ?

Thanks again
 
I would just call it a "bc variable". I called it "r" for "result". I assign a default result of 0, in case the if statement fails, it will still return a result. And, in fact... I did it incorrectly, because it prints the value of 0 even when you are *not* dividing by zero... [blush]

This is the correct version:

Code:
result=`echo "scale=2; r=0; if ($var3+$var4) [COLOR=red]r=[/color]100-(($var1+$var2)*100/($var3+$var4)); r" | bc`

Annihilannic.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top