(-2) %% 12 --- was a bug fix in 0.63.3 {{and musings about S ..}}
Martin Maechler
Martin Maechler <maechler@stat.math.ethz.ch>
Wed, 24 Mar 1999 11:37:24 +0100
>>>>> "PaulG" == Paul Gilbert <pgilbert@bank-banque-canada.ca> writes:
PaulG> (-2) %% 12 seems to give the wrong result in R pre 63.3:
>> e1 <- -2 ; e2 <- 12 ; e1 %% e2
PaulG> [1] -2
>> e1 - floor(e1/e2) * e2
PaulG> [1] 10
PaulG> In Splus:
>> e1 <- -2 ; e2 <- 12 ; e1 %% e2
PaulG> [1] 10
>> e1 - floor(e1/e2) * e2
PaulG> [1] 10
Thank you, Paul, for bringing up this topic (again).
Short answer:
This is has been changed in 0.63.3
and is mentioned in the "Bug Fixes" part of NEWS (and was even on R-announce!)
NEWS>>
NEWS>> o a %% b -- is now periodic instead of symmetric; more S compatible.
NEWS>>
Longer answer:
There are two problems:
1) ANSI C leaves the semantics of "a % b" (corresponding to R's "a %% b")
UNDEFINED whenever one of a or b is negative.
IMHO, this *is* a horrible fact (showing how little some computer scientists
care about mathematical computing..).
Older versions of R used to do what you mention above which is
what C (and hence R) do on at least Solaris and Linux-Intel.
2) S-plus DOES give different answers __solely__ depending on the
storage.mode of a (and/or b)
[being on the S version 4 mailing list, I've tried to start a
discussion on this,about a year ago, but nobody has even answered me...
So, the problem was not addressed for S-plus 5 and hence probably never will]
This is S-plus (any version AFAIK; certainly both 3.4 and 5.0 for Unix)
> version
Version 3.4 Release 1 for Sun SPARC, SunOS 5.3 : 1996
> d3 <- as.numeric(3) # 'd' for double
> i3 <- as.integer(3)
## These two differ, but I think they should not ...
> d3 %% c(-5:4)
[1] -2 -1 0 -1 0 3 0 1 0 3
> i3 %% c(-5:4)
[1] 3 3 0 1 0 3 0 1 0 3
> (-d3) %% c(-5:4)
[1] -3 -3 0 -1 0 -3 0 1 0 1
> (-i3) %% c(-5:4)
[1] 2 1 0 1 0 -3 0 1 0 1
>
---
The Current [0.63.3, but not earlier] and future versions of R
will be consistent and deliver
R> d3 <- as.numeric(3) # 'd' for double
R> i3 <- as.integer(3)
R> ## These two differ, but I think they should not ...
R> d3 %% c(-5:4) # -2 -1 0 -1 0 3 0 1 0 3
[1] -2 -1 0 -1 0 NaN 0 1 0 3
R> i3 %% c(-5:4) # 3 3 0 1 0 3 0 1 0 3
[1] -2 -1 0 -1 0 NA 0 1 0 3
R> (-d3) %% c(-5:4)# -3 -3 0 -1 0 -3 0 1 0 1
[1] -3 -3 0 -1 0 NaN 0 1 0 1
R> (-i3) %% c(-5:4)# 2 1 0 1 0 -3 0 1 0 1
[1] -3 -3 0 -1 0 NA 0 1 0 1
R>
Note that R's result now is the same, not depending on the storage.mode of
a or b.
The help page on "%%" now has a section
`%%' indicates `x mod y' and `%/%' indicates integer
division. It is guaranteed that `x == (x %% y) + y
* ( x %/% y )' unless `y == 0' where the result is `NA'
or `NaN' (depending on the `typeof' of the arguments).
----------------------
Remark:
In S version 4 (and S-plus 5.0)
"3" or "-3" are integers whereas they used to be
"numeric", i.e., "double" in Sv3 (i.e. S-plus x.y with x <= 4).
Consequence: S(plus) ``seems to'' be non backward compatible even in
this low level aspect:
Version 5.0 Release 3 for Sun SPARC, SunOS 5.5 : 1998 gives
> 11 %% -3
[1] 2
whereas Version 3.4 Release 1 for Sun SPARC, SunOS 5.3 : 1996 gives
> 11 %% -3
[1] -1
(and I still don't understand why nobody on the S version 4 beta list
had answered my concern then ...)
Martin
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-
r-devel mailing list -- Read http://www.ci.tuwien.ac.at/~hornik/R/R-FAQ.html
Send "info", "help", or "[un]subscribe"
(in the "body", not the subject !) To: r-devel-request@stat.math.ethz.ch
_._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._._