有趣的问题。这里是对上述回答者工作的另一个微调,矢量化,并扩展以处理小数点左侧的数字。针对负数进行了测试,前面的
strsplit()
方法会给出错误的结果。
如果只想计算右边的数字,则可以将
trailingonly
参数设置为
TRUE
。
nd1 <- function(xx,places=15,trailingonly=F) {
xx<-abs(xx);
if(length(xx)>1) {
fn<-sys.function();
return(sapply(xx,fn,places=places,trailingonly=trailingonly))};
if(xx %in% 0:9) return(!trailingonly+0);
mtch0<-round(xx,nds <- 0:places);
out <- nds[match(TRUE,mtch0==xx)];
if(trailingonly) return(out);
mtch1 <- floor(xx*10^-nds);
out + nds[match(TRUE,mtch1==0)]
}
这是
strsplit()
版本。
nd2 <- function(xx,trailingonly=F,...) if(length(xx)>1) {
fn<-sys.function();
return(sapply(xx,fn,trailingonly=trailingonly))
} else {
sum(c(nchar(strsplit(as.character(abs(xx)),'\\.')[[1]][ifelse(trailingonly, 2, T)]),0),na.rm=T);
}
字符串版本截断在15位数(实际上,不确定为什么另一个参数off by one...超过的原因是它在两个方向上计算数字,所以如果数字足够大,它可以增加到两倍大小)。可能有一些格式选项
as.character()
可以给
nd2()
提供与
nd1()
的
places
参数等效的选项。
nd1(c(1.1,-8.5,-5,145,5,10.15,pi,44532456.345243627,0))
nd2(c(1.1,-8.5,-5,145,5,10.15,pi,44532456.345243627,0))
nd1()
更快。
rowSums(replicate(10,system.time(replicate(100,nd1(c(1.1,-8.5,-5,145,5,10.15,pi,44532456.345243627,0))))));
rowSums(replicate(10,system.time(replicate(100,nd2(c(1.1,-8.5,-5,145,5,10.15,pi,44532456.345243627,0))))));