Matthieu Stigler
2008-Feb-18 12:17 UTC
[R] Number of digits of a value for problem 7.31 RFAQ
Hello dear R users! I did not find a function which gives information about the number of digits of a value shown by R. Do you know one? I need it to solve the problem (see RFAQ 7.31)that 0.2==0.2+0.1-0.1 FALSE The solution suggested in RFAQ is to use isTRUE(all.equal(0.2,0.2+0.1-0.1)) But if I want to compare inequality: 0.2<=0.2 +0.1-0.1 TRUE but 0.2<=0.2 +0.1-0.1 FALSE bad! but in this case all.equal does not work I think... Unless to write a double condition like 0.2>0.2 +0.1-0.1 | isTRUE(all.equal(0.2,0.2 +0.1-0.1)) The solution I found is to round the values, because 0.2==round(0.2+0.1-0.1,2) TRUE However, one has to know the number of digits of the target value. How can you do when it is unknown? What I mean is if R shows 2.3456 I want to obtain the info that digits=4 even if in facts the value has more (internal) digits. I did not find a way to represent the number of digits but I found that as.numeric(as.character(x)) rounds the values to the number of digits shown. But is there a better way to make it? Thanks!
Richard.Cotton at hsl.gov.uk
2008-Feb-18 12:57 UTC
[R] Number of digits of a value for problem 7.31 RFAQ
> I need it to solve the problem (see RFAQ 7.31)that 0.2==0.2+0.1-0.1FALSE> The solution suggested in RFAQ is to useisTRUE(all.equal(0.2,0.2+0.1-0.1))> > But if I want to compare inequality: > 0.2<=0.2 +0.1-0.1 TRUE > but 0.2<=0.2 +0.1-0.1 FALSE > bad! > but in this case all.equal does not work I think... Unless to write a > double condition like > 0.2>0.2 +0.1-0.1 | isTRUE(all.equal(0.2,0.2 +0.1-0.1)) > > The solution I found is to round the values, because > 0.2==round(0.2+0.1-0.1,2) TRUE > However, one has to know the number of digits of the target value. How > can you do when it is unknown?You can do this by using all.equal to check for cases close to the boundary: if(isTRUE(all.equal(0.2, 0.2 + 0.1 - 0.1))) { message("Possible rounding problems.") #investigate further } else if(0.2 <= 0.2 + 0.1 - 0.1) { #your code here } all.equal has a tolerance parameter that you can set to see how strict you want the equality to be; you may want to make this value smaller.> What I mean is if R shows 2.3456 I want to obtain the info that digits=4> even if in facts the value has more (internal) digits.Try: x = 1.23456789 format(x, nsmall=20) # [1] "1.23456788999999989009" Regards, Richie. Mathematical Sciences Unit HSL ------------------------------------------------------------------------ ATTENTION: This message contains privileged and confidential inform...{{dropped:20}}
Matthieu Stigler
2008-Feb-18 15:16 UTC
[R] Number of digits of a value for problem 7.31 RFAQ SOLVED not really
Matthieu Stigler a e'crit :> Richard.Cotton at hsl.gov.uk a e'crit : >>>> What I mean is if R shows 2.3456 I want to obtain the info that >> digits=4 >>>> even if in facts the value has more (internal) digits. >>> Try: >>> x = 1.23456789 >>> format(x, nsmall=20) >>> # [1] "1.23456788999999989009" >> >> I've just re-read the question. I suspect what you really wanted was >> something like: >> >> getndp <- function(x, tol=2*.Machine$double.eps) >> { >> ndp <- 0 >> while(!isTRUE(all.equal(x, round(x, ndp), tol=tol))) ndp <- ndp+1 >> if(ndp > -log10(tol)) warning("Tolerance reached, ndp possibly >> underestimated.") >> ndp } >> >> x = 0.123456 >> getndp(x) >> # [1] 6 >> >> x2 <- 3 >> getndp(x2) >> # [1] 0 >> x3 <- 0.1234567890123456789 >> getndp(x3) >> # [1] 16 >> # Warning message: >> # In getndp(x3) : Tolerance reached, ndp possibly underestimated. >> >> Regards, >> Richie. >> >> Mathematical Sciences Unit >> HSL >> > > Nice! Thanks a lot!! > Now I can solve my problem that: > > target<-0.223423874568437 > target<=target+0.1-0.1 #TRUE > target>=target+0.1-0.1 #FALSE!! > target==target+0.1-0.1 #FALSE!! > > by: > target<=round(target+0.1-0.1, getndp(target)) #TRUE > target>=round(target+0.1-0.1, getndp(target)) #TRUE!! > target==round(target+0.1-0.1, getndp(target)) #TRUE!! > >Actually (after some trials) there is a little problem when faced with zeros... >getndp(1.0) [1] 0 Note that it is only a partial problem because this happens only when the value is taken with other and so max(apply(matrix(allvalues,1,getndp))) will give the expected answer. But when faced with only one value... Note that I thought on a very different way which was starting from the point that as.character seems to work: a<-as.character(1.23134) b<-strsplit(a,"\\.") nchar(b) But I don't see how to do so that I can extract only the second element (maybe otherwise with sub or grep?)... But the method you gave is really more reliable than my "makeshift repair" Thanks again!