R语言 测试两个等于最低精度的数字

5anewei6  于 2022-12-20  发布在  其他
关注(0)|答案(2)|浏览(173)

给定两个数字数组,我想测试数字对的精度是否等于每一对数字中最不精确的数字的精度。
此问题源于验证所呈现数字的再现。我已获得一组(舍入)数字,尝试复制它们产生了更精确的数字。我需要报告较不精确的数字是否是更精确数字的舍入版本。
例如,以下向量对应全部返回true

input_a = c(0.01, 2.2, 3.33, 44.4, 560, 700) # less precise values provided
input_b = c(0.011, 2.22, 3.333, 44.4000004, 555, 660) # more precise replication

因为当舍入到最低成对精度时,两个向量相等:

pair_wise_precision = c(2, 1, 2, 1, -1, -2)

input_a_rounded = rep(NA, 6)
input_b_rounded = rep(NA, 6)

for(ii in 1:6){
  input_a_rounded[ii] = round(input_a[ii], pair_wise_precision[ii])
  input_b_rounded[ii] = round(input_b[ii], pair_wise_precision[ii])
}

all(input_a_rounded == input_b_rounded)
# TRUE
# ignoring machine precision

但是,我需要在不知道配对精度的情况下执行此操作。
我确定了两种方法:
1.测试舍入范围,如果任何舍入级别返回匹配,则接受两个值相等
1.预先计算每个输入的精度
然而,这两种方法都感觉很麻烦,我在另一种语言中看到过舍入一个数字以匹配另一个数字的精度的选项(抱歉,记不起来是哪个了),但我在R中找不到这个功能。
(This不是关于浮点数或由于机器精度而导致的不准确的问题。我很乐意分别处理这些。)
根据注解进行编辑:

  • 我们可以假设零不是有效数字,因此,1200四舍五入到最接近的100,530四舍五入到最接近的10,0.076四舍五入到最接近的千分之一。
  • 我们在最小精度值的精度处停止。因此,如果比较12300和12340,则最小精度值舍入到最接近的100,因此我们比较round(12300, -2)round(12340, -2)。如果比较530和570,则最小精度值舍入到最接近的10,因此我们比较round(530, -1)round(570, -1)
ryhaxcpt

ryhaxcpt1#

你可以除以10的指数,去掉后面的零,然后计算ncharpmin,其中你减去2的整数和小数点,这样你就得到了精度向量p,你可以用它四舍五入ab的底数,再乘以指数,然后检查identical

f <- \(a, b) {
  ae <- 10^floor(log10(a))
  be <- 10^floor(log10(b))
  al <- a/ae
  bl <- b/be
  p <- pmin(nchar(gsub('0+$', '', format(al))), nchar(gsub('0+$', '', format(bl)))) - 2L
  identical(mapply(round, al, p)*ae, mapply(round, bl, p)*be)
}

f(a, b)
# [1] TRUE
  • 数据:*
a <- c(0.01, 2.2, 3.33, 44.4, 555, 700)
b <- c(0.011, 2.22, 3.333, 44.4000004, 560, 660)
bihw5rsg

bihw5rsg2#

我最初的想法是按照@jay.sf的方法来分析数值,然而,将数值视为字符提供了另一种确定舍入的方法:

was_rounded_to = function(x){
  x = as.character(x)
  location_of_dot = as.numeric(regexpr("\\.", x))
  ref_point = ifelse(location_of_dot < 0, nchar(x), location_of_dot)
  last_non_zero = sapply(gregexpr("[1-9]", x), max)
  
  return(last_non_zero - ref_point)
}

# slight expansion in test cases
a <- c(0.01, 2.2, 3.33, 44.4, 555, 700, 530, 1110, 440, 3330)
b <- c(0.011, 2.22, 3.333, 44.4000004, 560, 660, 570, 1120, 4400, 3300)

rounding = pmin(was_rounded_to(a), was_rounded_to(b))

mapply(round, a, digits = rounding) == mapply(round, b, digits = rounding)

**特殊情况:**如果数值仅因舍入而不同,则通过检查差值更容易确定大小:

a <- c(0.01, 2.2, 3.33, 44.4, 555, 700)
b <- c(0.011, 2.22, 3.333, 44.4000004, 560, 660)

abs_diff = abs(a-b)
mag = -floor(log10(abs_diff ) + 1e-15)
mapply(round, a, digits = mag - 1) == mapply(round, b, digits = mag - 1)

但是,当数字相差超过舍入值时,此操作将失败。例如:a = 530b = 540将错误地将530和540四舍五入为500。

相关问题