I slightly disagree with that assessment. If it's not a bug, then
perhaps it's a feature request. Comments at the end.
On Mon, May 14, 2007, Duncan Murdoch wrote:
On 13/05/2007 8:46 PM, scott.wilkinson at csiro.au wrote:
In the example below round() does not report to the specified number of
digits when the last digit to be reported is zero: Compare behaviour for
0.897575 and 0.946251. Ditto for signif(). The number of sigfigs is
ambiguous unless the reader knows this behaviour. Is this a bug or
intended behaviour? Is there a work-around?
It's not a bug. It has nothing to do with round(), it is the way ROn 13/05/2007 8:46 PM, scott.wilkinson at csiro.au wrote:
In the example below round() does not report to the specified number of
digits when the last digit to be reported is zero: Compare behaviour for
0.897575 and 0.946251. Ditto for signif(). The number of sigfigs is
ambiguous unless the reader knows this behaviour. Is this a bug or
intended behaviour? Is there a work-around?
prints numbers by default. If you ask to print 0.90, you'll get
[1] 0.9
because 0.9 and 0.90 are the same number. If you want trailing zeros to
print, you need to specify a format to do that, e.g.
noquote(format(0.9, nsmall=2))
[1] 0.90The noquote stops the "" from printing. You could also use sprintf() or
formatC() for more C-like format specifications.
the decimal, don't they? Unless sprintf would default to the number of
decimal places passed to it, but it doesn't:
sprintf("%f",signif(0.90, digits=2))
[1] "0.900000";it defaults to 6. Although %g behaves differently,
sprintf("%g",signif(0.90, digits=2))
[1] "0.9",this clearly still isn't the desired behavior.
To continue that vein, the same issue with rounding versus printing
occurs with vectors:
sapply(c(1:6),function(a){signif(c(18.423,0.90),digits=a)})
[,1] [,2] [,3] [,4] [,5] [,6][1,] 20.0 18.0 18.4 18.42 18.423 18.423
[2,] 0.9 0.9 0.9 0.90 0.900 0.900
Trying to get that and more complicated tables to print the correct
number of significant digits gets pretty hairy with sprintf(). I could
be wrong, but I would view the primary purpose of rounding to
significant digits the printed output of the number. That there
doesn't seem to be a way to do this without later having to specify
the number of decimal places would seem to render signif() as it's
written not particularly useful.
There are two solutions I can think of off the top of my head. The
first is to create a new data type of a fixed length real number but
the easier way would be to have a function that returns a string
something like this:
signif.string <- function(signum,sigdigs){
left <- nchar(trunc(signum))
right <- nchar(signum-trunc(signum))-2
if (abs(signum)<1 | signum<0) {left<-left-1}
if (right<0) {right<-0}
if (sigdigs<left) {return(as.character(signif(signum,digits=sigdigs)))}
else if (sigdigs==left) {return(paste(round(signum),".",sep=""))}
else if (sigdigs<=left+right) {return(format(signum,digits=sigdigs))}
else {return(sprintf(paste("%.",sigdigs-left,"f",sep=""),signum))}
}
This is just a skeleton that I think suits my needs for the moment and
might also cover the original poster's. One for production would need
to handle scientific notation and would probably want to fix the 5
round behavior on windows.
Pat Carr
version.string R version 2.7.0 (2008-04-22)