Re: remainder() is not right
- Posted by CChris <christian.cuvier at agr?culture.go?v.fr> May 04, 2008
- 1075 views
jacques deschĂȘnes wrote: > > 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 > True. And signed_remainder() also respects this identity. But see, there are at least two ways of defining it, the mathematic way and the C way. CChris > 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