1. Round

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

new topic     » topic index » view message » categorize

2. Re: Round

To answer (c)koda's original question,  what you are looking for is
something like the old G(ee)W(hizz) Basic integer command.
This converts a decimal to an integer - quite handy for some things.
The way I do it is:

function force_integer(atom number)
    number=floor(sqrt(number*number)+0.5)*

(number/(sqrt(number*number))
    return number
end function

I also have this in a loop to round strings, as a round function which has
number_of_decimal_places as an argument. The absolute value (sqrt(num*num))
is multiplied by power(10,num_places) and the final result divided by
power(10,num_places).

Kind Regards,
Aidan

new topic     » goto parent     » topic index » view message » categorize

3. Re: Round

I have some things to address here that I am surprised haven't been
mentioned by someone else yet.

Your code....
    sqrt(number*number)--abs()
I only see one flaw in this absolute value code.  Yes, it works.  Yes, it
will most likely work in every case that you ever use it in.  No it doesn't
work for all atoms.  In fact it doesn't come close to working with all
atoms.

Example:
I start with a with a value that is much less than half the atoms possible.

  a = largest_possible_atom / 3
  a = sqrt(a*a)--Oops....  the poor thang crashed.

--lets say way break the above line down and see why.
  a = (a*a)--Oops... the poor than crashed...

--Now let's analyze why.
TRUE or FALSE !!!
  largest_possible_atom is greater than 3?
  (6/2) * (6/2) equals 9?
  9 is greater than 6?
Assume that 6 is the largest_possible_atom
You know that 9 is greater than 6.
Therefore 9 is large enough to crash the program.

You know that Half of 6 is 3 AND
3 times 3 = 9
You can see that your math will keep more than half of the possible atoms
from being evaluated.

function your_abs(atom a)--You
  return sqrt(a * a)
end function

function my_abs()
  if a > 0 then
    return a
  else
    return -a
  end if
end function



NEXT

You said "I also have this in a loop to round strings".  I assume you mean
the following example.

i =  force_integer(4.3) -- i = 4
s = repeat(i, 3)--{4.3, 4.3, 4.3}
for A = 1 to length(s) do
  s[A] = force_integer(s[A])
end for
--s = {4, 4, 4}

If this is the case and the method in which you handle a long set of
integers, then wake up and realize the power of sequences.  The math will
work on an entire sequence just as easily as it will work on and individual
atom.

In your code listed below just change:

function force_integer(atom number)
     TO
function force_integer(object number)

        Lucius L. Hilley III
        lhilley at cdc.net
+----------+--------------+--------------+
| Hollow   | ICQ: 9638898 | AIM: LLHIII  |
|  Horse   +--------------+--------------+
| Software | http://www.cdc.net/~lhilley |
+----------+-----------------------------+

----- Original Message -----
From: "Aidan Bindoff" <abindoff at one.net.au>
To: <EUPHORIA at LISTSERV.MUOHIO.EDU>
Sent: Thursday, June 08, 2000 7:02 PM
Subject: Re: Round


> To answer (c)koda's original question,  what you are looking for is
> something like the old G(ee)W(hizz) Basic integer command.
> This converts a decimal to an integer - quite handy for some things.
> The way I do it is:
>
> function force_integer(atom number)
>     number=floor(sqrt(number*number)+0.5)*
>
> (number/(sqrt(number*number))
>     return number
> end function
>
> I also have this in a loop to round strings, as a round function which has
> number_of_decimal_places as an argument. The absolute value
(sqrt(num*num))
> is multiplied by power(10,num_places) and the final result divided by
> power(10,num_places).
>
> Kind Regards,
> Aidan
>

new topic     » goto parent     » topic index » view message » categorize

4. Re: Round

Lucius, thankyou for pointing that out. In my applications I hadn't even
considered atoms that big. Also, making a loop does seem pretty convoluted
when you can just use force_int(object) - but that's Euphoria!  You don't
always wake up and smell the coffee with everything different thing you
do...

Kind Regards,
Aidan
----- Original Message -----
From: Lucius L. Hilley III <lhilley at CDC.NET>
To: <EUPHORIA at LISTSERV.MUOHIO.EDU>
Sent: Friday, June 09, 2000 10:55 PM
Subject: Re: Round


>     I have some things to address here that I am surprised haven't been
> mentioned by someone else yet.
>
> Your code....
>     sqrt(number*number)--abs()
> I only see one flaw in this absolute value code.  Yes, it works.  Yes, it
> will most likely work in every case that you ever use it in.  No it
doesn't
> work for all atoms.  In fact it doesn't come close to working with all
> atoms.
>
> Example:
> I start with a with a value that is much less than half the atoms
possible.
>
>   a = largest_possible_atom / 3
>   a = sqrt(a*a)--Oops....  the poor thang crashed.
>
> --lets say way break the above line down and see why.
>   a = (a*a)--Oops... the poor than crashed...
>
> --Now let's analyze why.
> TRUE or FALSE !!!
>   largest_possible_atom is greater than 3?
>   (6/2) * (6/2) equals 9?
>   9 is greater than 6?
> Assume that 6 is the largest_possible_atom
> You know that 9 is greater than 6.
> Therefore 9 is large enough to crash the program.
>
> You know that Half of 6 is 3 AND
> 3 times 3 = 9
> You can see that your math will keep more than half of the possible atoms
> from being evaluated.
>
> function your_abs(atom a)--You
>   return sqrt(a * a)
> end function
>
> function my_abs()
>   if a > 0 then
>     return a
>   else
>     return -a
>   end if
> end function
>
>
>
> NEXT
>
> You said "I also have this in a loop to round strings".  I assume you mean
> the following example.
>
> i =  force_integer(4.3) -- i = 4
> s = repeat(i, 3)--{4.3, 4.3, 4.3}
> for A = 1 to length(s) do
>   s[A] = force_integer(s[A])
> end for
> --s = {4, 4, 4}
>
> If this is the case and the method in which you handle a long set of
> integers, then wake up and realize the power of sequences.  The math will
> work on an entire sequence just as easily as it will work on and
individual
> atom.
>
> In your code listed below just change:
>
> function force_integer(atom number)
>      TO
> function force_integer(object number)
>
>         Lucius L. Hilley III
>         lhilley at cdc.net
> +----------+--------------+--------------+
> | Hollow   | ICQ: 9638898 | AIM: LLHIII  |
> |  Horse   +--------------+--------------+
> | Software | http://www.cdc.net/~lhilley |
> +----------+-----------------------------+

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu