strange ksh arithmetic

Hello,

I would like to understand this... I'm using ksh and doing

(( z = y - 1 ))

if y=34, then the result for z is 33, but if y=034 the result is z=27. Why??

Thanks

try

typeset -i y=0
#............. forces y to be an integer value

The '0' signals the shell to interpret that value as octal. So 034 (decimal 28) minus 1 equals 27 (decimal)

Thanks! I just wanted to understand...

I have

n=23

then I do

nan=`grep -c -i 'NaN' file`

so that nan is a variable with the number of lines with the field "NaN" in file. Then I do

(( n = n - nan ))

and when nan=0, instead of n=23 I get n="nan". Why is that?

Because it's (( n = $n - $nan ))
If you want to use a variable, you have to prefix it with '$', as opposed to declaring it. If you want to use a variable in some text, the preferred method would be ${variable}

Thanks pludi, my ksh was updated to ksh-20080202-2.el5 from a 2006 version. Now my old scripts are all crashing with this. The older version was more flexible, I think.

Hi.

This seems to work for me in the 3 shells noted:

#!/usr/bin/env bash
#!/usr/bin/env zsh
#!/usr/bin/env ksh

# @(#) s1       Demonstrate feature.

echo
set +o nounset
LC_ALL=C ; LANG=C ; export LC_ALL LANG
echo "Environment: LC_ALL = $LC_ALL, LANG = $LANG"
echo "(Versions displayed with local utility \"version\")"
version >/dev/null 2>&1 && version "=o" $(_eat $0 $1) grep
set -o nounset

FILE=${1-data1}
echo
echo " Contents of data file $FILE:"
cat $FILE

# Initialize to help isolate errors.
n=""
nan=""

n=23
nan=`grep -i -c nan $FILE`

echo
echo " Results:"
echo " Before arithmetic:  nan = $nan, n = $n"
(( n = n - nan ))
echo " After  arithmetic:  nan = $nan, n = $n"

n=5
nan=-3
echo
echo " Results:"
echo " Before arithmetic:  nan = $nan, n = $n"
(( n = n - nan ))
echo " After  arithmetic:  nan = $nan, n = $n"

exit 0

Producing:

% ./s1 data2

Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 2.6.11-x1, i686
Distribution        : Xandros Desktop 3.0.3 Business
GNU bash 2.05b.0
grep (GNU grep) 2.5.1

 Contents of data file data2:
Now is the time
for all good men
to come to the aid
of their country.

 Results:
 Before arithmetic:  nan = 0, n = 23
 After  arithmetic:  nan = 0, n = 23

 Results:
 Before arithmetic:  nan = -3, n = 5
 After  arithmetic:  nan = -3, n = 8

For some shells, (( and let allow:

For the specific case mentioned by the OP, perhaps printing out the values, using "-x", etc., will help pin-point the problem ... cheers, drl

Hi.

The versions of ksh 93s and 93t failed as noted by the OP. Confirmed success with bash and zsh on Debian lenny and Fedora 10 ... cheers, drl

It is better to use the standard POSIX syntax for arithmetic:

z=$(( $y - 1 ))

Numbers beginning with 0 are interpreted as octal numbers.

Hi.

I think the string nan is an undocumented reserved word in ksh 93. In this script, I changed the variable name from nan to nn, and the expressions worked as we think they should. At the end of the script, I set and echoed the variables nin and nan, which printed differently:

#!/usr/bin/env ksh

# @(#) s4       Demonstrate arithmetic with (( expression )).

echo
set +o nounset
LC_ALL=C ; LANG=C ; export LC_ALL LANG
echo "Environment: LC_ALL = $LC_ALL, LANG = $LANG"
echo "(Versions displayed with local utility \"version\")"
version >/dev/null 2>&1 && version "=o" $(_eat $0 $1) grep
set -o nounset

FILE=${1-data3}
echo
echo " Contents of data file $FILE:"
cat $FILE

# Initialize to help isolate errors.
n=""
nn=""

n=23
nn=`grep -i -c nn $FILE`

echo
echo " Results:"
echo " Before arithmetic:  nn = $nn, n = $n"
(( n = n - nn ))
echo " After  arithmetic:  nn = $nn, n = $n"

n=5
nn=-3
echo
echo " Results:"
echo " Before arithmetic:  nn = $nn, n = $n"
(( n = n - nn ))
echo " After  arithmetic:  nn = $nn, n = $n"

nin=""
echo
echo " The string nin is:"
echo $(( nin ))

nan=""
echo
echo " The string nan is:"
echo $(( nan ))

exit 0

Producing:

$ ./s4

Environment: LC_ALL = C, LANG = C
(Versions displayed with local utility "version")
OS, ker|rel, machine: Linux, 2.6.26-1-686, i686
Distribution        : Debian GNU/Linux 5.0
ksh 93s+
GNU grep 2.5.3

 Contents of data file data3:
Now is the time
nn
for all good men
nn
to come to the aid
of their country.

 Results:
 Before arithmetic:  nn = 2, n = 23
 After  arithmetic:  nn = 2, n = 21

 Results:
 Before arithmetic:  nn = -3, n = 5
 After  arithmetic:  nn = -3, n = 8

 The string nin is:
0

 The string nan is:
nan

The variable nan vaguely bothered me because it means NaN, Not a Number, in IEEE standards (some details at NaN - Wikipedia, the free encyclopedia ). I also noticed a reference to the C function isnan in the man page for ksh (ksh 93).

Best wishes ... cheers, drl

No, it's not.

In the code you posted, you don't do anything with $nan, so there is nothing to show the error.

Post code which does show the error.

And use POSIX syntax for arithmetic so that you can compare the results in other shells.

Hi.

The last section of the code sets 2 variables, nin and nan to the null string. It then uses POSIX arithmetic to evaluate those expressions. The nin prints as "0", whereas the nan prints as "nan".

That was to show that changing the variable name in the (second) OP code from nan to nn corrects the problem ... cheers, drl

That was all you needed to post.

On my version of ksh93 (as well as pdksh and bash) that code prints 0 for both cases.

I cannot reproduce the problem. What version of ksh93 are you using?

Hi.

I am trying to help the OP solve his problem in an efficient way, so it makes sense to me to post the heart of his code with a correction that makes it work. If that can be done with a change of variable name, that seems easier than changing to the POSIX evaluation. He may still want to change to POSIX as his schedule allows, but most people need to get work done. The last part of the code is to show how using the string nan as a variable does not do what we might expect.

Same here for pdksh and bash, as well as zsh -- at least for all versions under which I ran the script s4.

As noted in the listing of OS and command versions in the output, that was done with ksh 93s+. As noted in post #9, the nan issue is present in 93s and 93t.

Best wishes ... cheers, drl

"ksh93 performs all calculations using the double precision floating point arithmetic type on your system." The New Kornshell Command and Programming Language by Bolsky and Korn.

So now you need to understand floating point arithmetic. If it's ieee floating point, +NaN, -NaN, +Inf, and -Inf must be supported. ksh93 has been stumbling on those constants, but the intent is to support ieee as fully as your system does.

NaN = not a number
Inf = infinity

In the ksh mailing list, they are always spelled NaN and Inf, I don't know if the all lower case spelling is considered to be acceptable. Some systems, and Cray comes very quickly to mind, do not support ieee floating point and cannot deal with NaN and Inf.

This is about all I know about nan and ksh93, so I can't shed much more light.

See this thread: https://mailman.research.att.com/pipermail/ast-users/2006q4/001468.html