Re: remainder() is not right

new topic     » goto parent     » topic index » view thread      » older message » newer message

In fact remainder(x,y) means   q*y+r=x
so 
   remainder(-27,3600)= (-27) is ok as  0*3600+(-27)=(-27)
   remainder(-3627,3600)=(-27) is ok as -1*3600+(-27)=(-3627)
   remainder(-3627,-3600) = -27 is ok as 1*(-3600)+(-27)=(-3627)
   remainder(27,-3600) = 27 is ok as 0*3600+ 27 = 27

Jacques DeschĂȘnes

CChris wrote:
> 
> 
> The remainder of x by y, which remainder() is supposed to return, is the
> number
> with the smallest magnitude and the sign of y such that, if we call it z, x-z
> is a multiple of y.
> 
> But remainder() has a quirkier response. For instance:
> ?remainder(-27,3600) -- -27, instead of 3573
> ?remainder(-3627,3600) -- ditto
> ?remainder(-3627,-3600) -- -27 is correct here
> ?remainder(27,-3600)    -- 27, instead of -3573
> 
> Changing remainder()'s behaviour will break any code that works around this
> behaviour. So perhaps should we add another function with the appropriate
> return
> values; perhaps signed_remainder()?
> 
> Notionally, it might work like this:
> }}}
<eucode>
> global function signed_remainder(object a,object b)
>     integer atom_a,atom_b
>     atom c
> 
>     if find(b,{{},0.0} then
>         return {} -- not a valid 2nd argument
>         -- crash("Invalid 2nd argument to remainder()")
>     end if
>     atom_a=atom(a)
>     atom_b=atom(b)
>     if atom_a!=atom_b then
>         if atom_a then -- atom,sequence
>             for i=1 to length(b) do
>                 b[i]=signed_remainder(a,b[i])
>             end for
>             return b
>          else -- sequence,atom
>              for i=1 to length(a) do
>                  a[i]=signed_remainder(a[i],b)
>              end for
>              return a
>         end if
>     elsif atom_a=0 then -- two sequences
>         if length(a)!=length(b) then
>             return {} -- let caller handle the mismatch
>             -- crash("Sequence lengths don't match")
>         else
>             for i=1 to length(a) do
>                 a[i]=signed_remainder(a[i],b[i])
>             end for
>             return a
>         end if
>     else -- two atoms
>         c=remainder(a,b) -- smallest magnitude and sign of a
>         if a<0!=b<0 then
>             return c+b
>         else
>             return c
>         end if
> end function
> </eucode>
{{{

> 
> It will be probably better implemented as a builtin if there is a
> corresponding
> C stdlib function with the desired behaviour. If only to take advantage of the
> sequence extension mechanism binary_op() in be_runtime.c provides.
> 
> CChris

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu