Round
- Posted by Michael Nelson <mike-nelson-ODAAT at WORLDNET.ATT.NET> Jun 07, 2000
- 618 views
The following code may be of interest: global function unary_function(integer id,object Param) if atom(Param) then return call_func(id,{Param}) end if for i=1 to length(Param) do Param[i]=call_func(id,{Param[i]}) end for return Param end function global function binary_function(integer id,object Param1,object Param2) integer len1,len2 if atom(Param1) then len1=-1 else len1=length(Param1) end if if atom(Param2) then len2=-1 else len2=length(Param2) end if if len1=-1 and len2=-1 then return call_func(id,{Param1,Param2}) end if if len1=-1 then Param1=repeat(Param1,len2) len1=len2 elsif len2=-1 then Param2=repeat(Param2,len1) len2=len1 end if if len1!=len2 then puts(2,"\nSequence length mismatch.\n") ? 1/0 end if for i=1 to len1 do Param1[i]=call_func(id,{Param1[i],Param2[i]}) end for return Param1 end function constant TOLERANCE=1e-10 function round_atom(atom a,integer places) integer int atom adjust adjust=power(10,places) a=a*adjust+.5 int=floor(a) if a-int<TOLERANCE and remainder(int,2)!=0 then int-=1 end if return int/adjust end function constant ROUND_ATOM=routine_id("round_atom") global function round(object x,object places) return binary_function(ROUND_ATOM,x,places) end function First look at round_atom(). This rounds an atom to the specified number of places (use 0 to round to an integer). The floor(a+.5) idea works except for exact .5 remainders--it can round these wrong. The code I have given above aproximates the IEEE standard "Banker's Rounding": round .4999999 down, round .5000001 up, round exactly .5 to the nearest even number. This can't be done exactly with Euphoria's binary floating point atoms, but the tolerance factor gets it right most of the time. (Getting it right every time requires binary coded decimal fp.) If you prefer a 5/4 roundoff, where exactly .5 is rounded up change if a-int<TOLERANCE and remainder(int,2)!=0 then int-=1 end if to if a-int<TOLERANCE and a<=0 then int-=1 end if The function round() extends this to allow for sequences so that ? round(1.5,0) -->prints 2 ? round(3.14159,{0,1,2,3,4}) -->prints {3,3.1,3.14,3.142,3.1416} ? round({15.786,12.3455},2) -->prints {15.79,12.35} and so forth. The utility functions unary_function() and binary_function() are used apply functions written to use atoms to sequences. Use unary_function() if the atomic function takes 1 argument, binary_function() if 2. -- Mike Nelson