On Thu, Sep 19, 2013 at 3:28 AM, Tina Harriott <[email protected]> wrote: > On 11 August 2013 10:43, Tina Harriott <[email protected]> wrote: >> On Wed, Jul 24, 2013 at 7:28 PM, Glenn Fowler <[email protected]> wrote: >>> On Wed, 24 Jul 2013 19:02:39 +0200 Tina Harriott wrote: >>>> Here's one of my little tough problems which I am unable to solve >>>> myself, even after looking at the source code of ast-ksh. The problem >>>> below requires a good understanding how floating point numbers are >>>> implemented in computers. >>> >>>> I'm trying to prototype code and like to iterate over a small, linear >>>> area by using the C library function nextafter() to step forward the >>>> smallest possible distance between each step, and print the number of >>>> iterations needed to cover the distance between 4 and 4.000000000001: >>>> ksh -c 'float v ; integer iter ; for ((iter=0,v=4 ; v < 4.000000000001 >>>> && iter < 10000000; v=nextafter(v,4.000000000001))) ; do >>>> ((iter++));done;print $iter ' >>>> 2305843 >>> >>>> The result 2305843 is correct. >>> >>>> However, if I use typeset -E (or just typeset) to declare the variable >>>> v the loop runs forever, or in this case until it hits iter < 10000000 >>>> which I added as safeguard later: >>>> ksh -c 'typeset -E v ; integer iter ; for ((iter=0,v=4 ; v < >>>> 4.000000000001 && iter < 10000000; v=nextafter(v,4.000000000001))) ; >>>> do ((iter++));done;print $iter ' >>>> 10000000 >>> >>>> Can anyone explain this? >>> >>> float is an alias >>> this shows the alias definition >>> type float >>> which is >>> typeset -lE >>> this documents -l >>> typeset --?l >>> >>> so for your example >>> typeset -E >>> gave you a double v and >>> typeset -lE >>> would give you a "long double" v >> >> But why does nextafter() misbehave if I want to use a datatype smaller >> than "long double"? Accuracy is a good thing, but in this case we >> iterate too fine-grained, meaning the code should iterate over the >> smallest possible steps of a double, but not over the smallest >> possible steps of a long double. > > The test still doesn't work: > > typeset -E v ; integer iter > for ((iter=0,v=4 ; v < 4.000000000001 && iter < 10000000; > v=nextafter(v,4.000000000001))) ;do > ((iter++)) > done > print $iter > > ~/bin/ksh --version > version sh (AT&T Research) 93v- 2013-09-13 > ~/bin/ksh x.sh > 10000000 > > Is it very hard to integrate the fix Mr. Mainz send? My professor is > asking for a solution (ksh, or switch to perl or python)
Erm... my patch wasn't exactly flawless... AFAIK the issues are: 1. My patch only looked at the first argument to determinate the datatype of the function needed and not both 2. Something like nextafter(x+1.1,5) causes issue because it raises the question of the datatype of the result of |x+1.5|. If we ally the C99 ruleset we get something like this: x==|float|, then the datatype of |x+1.5| is |double|, because |1.5| is a |double| x==|double|, then the datatype of |x+1.5| is |double|, because both |1.5| and |x| are |double|s x==|long double|, then the datatype of |x+1.5| is |long double|, because |x| is a |long double| A solution to get [2] under control is to add type suffixes to constants, e.g. |1.5F| is a |float|, |1.5| is a |double| and |1.5L| is a |long double|. A different way may be to bind the type of function to a variable, e.g. do this: -- snip -- typeset -s -E v ; ... ; v.nextafter() # calls |nextafterf()| because v is a |float| typeset -E v ; ... ; v.nextafter() # calls |nextafter()| because v is a |double| typeset -l -E v ; ... ; v.nextafter() # calls |nextafterl()| because v is a |long double| -- snip -- ... but that can only be done optionally because $((...))/((...)) arithmetic expressions should work like ISO C if possible... ---- Bye, Roland -- __ . . __ (o.\ \/ /.o) [email protected] \__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer /O /==\ O\ TEL +49 641 3992797 (;O/ \/ \O;) _______________________________________________ ast-developers mailing list [email protected] http://lists.research.att.com/mailman/listinfo/ast-developers
