Интересный вопрос. Вот еще один твик работы вышеупомянутых респондентов, векторизованный и расширенный для обработки цифр слева от десятичной точки. Проверено на наличие отрицательных цифр, которые дают неверный результат для предыдущего подхода 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 цифр (на самом деле, не уверен, почему аргумент места другого отключен на одну единицу ... причина, по которой он превышен, заключается в том, что он считает цифры в обоих направлениях, чтобы он мог увеличиться вдвое размер, если число достаточно большое). Вероятно, есть некоторая опция форматирования для as.character()
, которая может дать nd2()
эквивалентную опцию для аргумента places
nd1()
.
nd1(c(1.1,-8.5,-5,145,5,10.15,pi,44532456.345243627,0));
# 2 2 1 3 1 4 16 17 1
nd2(c(1.1,-8.5,-5,145,5,10.15,pi,44532456.345243627,0));
# 2 2 1 3 1 4 15 15 1
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))))));