I'm looking for a routine that would round a vector by the "necessary" number of digits so that all elements are still distinguishable. My first attempt looks like this:
discr.round <- function(x) {
digits <- ceiling(-min(log10(diff(sort(x)))))
round(x, digits)
}
discr.round(c(12.336, 12.344))
# [1] 12.336 12.344
discr.round(c(12.336, 12.347))
# [1] 12.34 12.35
discr.round(c(10, 25, 39))
# [1] 10 20 40
discr.round(c(1.2345679, 1.2345681))
# [1] 1.234568 1.234568
discr.round(c(1.23456789, 1.23456791))
# [1] 1.234568 1.234568
I need this to format a vector of floating-point numbers using "few" decimal places.
How would this kind of rounding be called? Is there a "standard" implementation of this or a similar logic, in base R or a package?
EDIT: I need this for pairs, but the code should generalize to vectors of arbitrary length. If the numbers are exactly equal, they do not need to be discriminated.
options(digits=12) # Part of the problem is that your default digits = 7,
# so you won't see any digits beyond that.
# If you put too many (e.g, 22), you'll get floating point imprecision
# Note the behavior for rounding off a 5 under ?round:
# "IEC 60559 standard is expected to be used, ‘go to the even digit’."
# digits needed to distinguish between two nonequal elements
diff.dec.places <- function(x, y){
delta <- abs(x - y)
dec.place <- -ceiling(log10(abs(delta))) # your idea here was correct
print(paste0("The elements (",x," & ",y,") differ in the ",
10^-dec.place,"'s place."))
if(round(x, dec.place)==round(y, dec.place)){
print("But we add another sig. figure so they do not round to the same number.")
dec.place <- dec.place + 1
}
print(paste("The elements will round to",round(x, dec.place),'&',round(y, dec.place)))
dec.place
}
# formula for arbitrary number of elements:
discr.round <- function(x){
#- Find minimum-magnitude difference and which elements possess it:
#- Create upper triangle of difference matrix of elements of vector with itself
d <- abs(outer(x,x,"-"))
d[lower.tri(d, diag=T)] <- NA
#- Return the smallest-magnitude difference and indices of elements forming it
m <- min(d, na.rm=T)
if(m != 0){
#- Round to number of dec places required to distinguish the closest elements
e <- x[which(d==m, arr.ind=T)]
round(x, diff.dec.places(e[1],e[2]))
}
else{
print("Closest elements are equal.")
x
}
}
discr.round(c(12.336, 12.344))
# [1] 12.336 12.344
discr.round(c(12.336, 12.347))
# [1] 12.34 12.35
discr.round(c(10, 25, 39))
# [1] 10 20 40
discr.round(c(1.2345679, 1.2345681))
# [1] 1.2345679 1.2345681
discr.round(c(1.23456789, 1.23456791))
# [1] 1.23456789 1.23456791
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With