On Mon, Sep 03, 2007 at 08:59:22AM +0200, [EMAIL PROTECTED] wrote: > Full_Name: Marco Vicentini, University of Verona > Version: 2.4.1 & 2.5.1 > OS: OsX & WinXP > Submission from: (NULL) (157.27.253.46) > > > When I proceed to test the following equation 1 + 2 == 3, I obviously obtain > the > value TRUE. But when I tryed to do the same using real number (i.e. 0.1 + 0.2 > == > 0.3) I obtained an unusual FALSE. > In the online help there are some tricks for this problem. It suggests to use > identical(...) which again answer FALSE. Only using isTRUE(all.equal(0.3, 0.1 > + > 0.2)) I can obtain the true value TRUE.
A rational number has a finite binary expansion iff its denominator is a power of 2. Numbers 0.1 and 0.2 are 1/10 and 1/5, so they have 5 in their denominator. Their binary expansion is 0.1 = .0001100110011001100110011001100110... 0.2 = .0011001100110011001100110011001100... A double variable stores the numbers rounded to 53 significant binary digits. Hence, they are not exactly 0.1 and 0.2, as may be seen in formatC(0.1,digits=30) # [1] "0.100000000000000005551115123126" formatC(0.2,digits=30) # [1] "0.200000000000000011102230246252" In order to compare numbers with some tolerance, the function all.equal may be used, which you also mention below. See its help page, which specifies the tolerance to be .Machine$double.eps ^ 0.5. > But the problem does not concern only the operator ==. Many other functions, > among over: sort, order, unique, duplicate, identical are not able to deal > with > this problem. This is very dangerous because no advice are provide by the > online > help, and anybody can use these functions no think to unusual results. > > I think that the problem is due to how double number are store by the C > compiler. Not C compiler, but the hardware. Petr Savicky. > If it may be usefull, I have written to small function (Unique and isEqual) > which can deal with this problem of the double numbers. > > I also add some other conditions for the same problem. > > 0.3 == 0.15 + 0.15 > 0.3 == 0.1 + 0.2 > 1 - 0.7 == 0.3 > 0.1 == 1 - 0.9 > > 0.2 == 1 - 0.2 - 0.2 - 0.2 - 0.2 > -0.2 == 1 - 0.2 - 0.2 - 0.2 - 0.2 - 0.2 - 0.2 > > identical (0.3, 0.1 + 0.2) > all.equal (0.3, 0.1 + 0.2) > > identical (-0.2 , 1 - 0.2 - 0.2 - 0.2 - 0.2 - 0.2 - 0.2) > all.equal (-0.2 , 1 - 0.2 - 0.2 - 0.2 - 0.2 - 0.2 - 0.2) > > isTRUE( all.equal (-0.2 , 1 - 0.2 - 0.2 - 0.2 - 0.2 - 0.2 - 0.2) ) > > > -0.2 == 1 - 0.2 - 0.2 - 0.2 - 0.2 - 0.2 - 0.2 > > a= -0.2 > b= 1 - 0.2 - 0.2 - 0.2 - 0.2 - 0.2 - 0.2 > > x<-c(a,b) > sprintf("%.15f",x) > sprintf("%.50f",x) > > > > Unique <- function(x, digits = 8, fast = TRUE) { > > if (fast) { > unique (round(x * 10^digits)) / 10^digits > } else { > x = sort(x) > for (i in 1:(length(x)-1)) > if (isTRUE(all.equal(x[i],x[i+1]))) x[i] = NaN > x [ which (!is.nan(x)) ] > }} > > isEqual <- function (object, x, tol = 1e-9) { > if (!is.vector(object)) stop("Object must be a vector") > if (is.character(object)) stop("Object can not be a character") > if (!is.real(x)) stop("x must be a real number") > if (any(is.na(c(object,x)))) stop("NA is not supported") > if (length(x) != 1) stop("length x must equal to 1") > > ifelse (abs(object - x) < tol, TRUE,FALSE) > # .Call("isEqual",as.real(object),as.real(x),as.real(tol), > PACKAGE="mvUtils") > } > > ______________________________________________ > R-devel@r-project.org mailing list > https://stat.ethz.ch/mailman/listinfo/r-devel > ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel