如何在R中按数值对的最低精度验证两组数值是否匹配
验证两组数值按成对最低精度取整后的相等性
我们需要验证两组数值数组中,每一对数值按该对中精度最低的数值的精度取整后是否相等。这个需求来自数值复现验证:已知一组经过取整的低精度数值,复现得到更高精度的结果,要确认低精度数值是否是高精度数值的取整版本。
示例(验证结果应为TRUE)
给定两组向量:
input_a = c(0.01, 2.2, 3.33, 44.4, 560, 700) # 给定的低精度数值 input_b = c(0.011, 2.22, 3.333, 44.4000004, 555, 660) # 复现得到的高精度数值
手动指定成对精度后验证,结果为TRUE:
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) # [1] TRUE # 忽略机器精度误差
现有思路的问题
目前想到两种方法,但都较为繁琐:
- 测试多个取整精度,只要任意精度下匹配就判定相等
- 预先计算每个输入数值的精度
之前在其他语言中见过将一个数值取整到另一个数值精度的功能,但未在R中找到现成实现。
注:此问题与浮点数/机器精度误差无关,该部分已单独处理。
补充规则
- 零不视为有效数字:例如
1200视为取整到百位,530视为取整到十位,0.076视为取整到千分位。 - 取整精度以成对数值中精度最低的那个为准:比如比较
12300和12340时,最低精度是百位,需比较round(12300, -2)和round(12340, -2);比较530和570时,最低精度是十位,需比较round(530, -1)和round(570, -1)。
解决方案
我们可以实现两个函数:一个用于计算单个数值的精度(即round函数的第二个参数),另一个用于自动完成验证逻辑。
1. 计算单个数值的精度
get_precision <- function(x) { # 处理0的情况(可根据实际需求调整精度定义) if (x == 0) return(0) # 转换为非科学计数法的字符串 x_str <- format(x, scientific = FALSE, trim = TRUE) # 拆分整数和小数部分 parts <- strsplit(x_str, "\\.")[[1]] if (length(parts) == 1) { # 整数情况:统计末尾连续0的个数,精度为负的个数 integer_part <- parts[1] trailing_zeros <- nchar(gsub("[^0]+$", "", integer_part)) return(-trailing_zeros) } else { # 小数情况:找到最后一个非0数字的位置,即为精度值 decimal_part <- parts[2] last_non_zero_pos <- max(gregexpr("[^0]", decimal_part)[[1]]) return(last_non_zero_pos) } }
2. 自动验证函数
verify_rounded_equal <- function(a, b) { # 检查向量长度是否一致 if (length(a) != length(b)) stop("两组向量长度必须相同") # 计算每个元素的精度 prec_a <- sapply(a, get_precision) prec_b <- sapply(b, get_precision) # 取每对数值中的最低精度(精度值越小,精度越低) pair_prec <- pmin(prec_a, prec_b) # 按对应精度取整并比较 rounded_a <- mapply(round, a, pair_prec) rounded_b <- mapply(round, b, pair_prec) # 返回全部相等的判断结果 all(rounded_a == rounded_b) }
测试验证
用示例数据测试:
verify_rounded_equal(input_a, input_b) # [1] TRUE
其他测试案例:
# 案例1:12300与12340,取整到百位后相等 verify_rounded_equal(c(12300), c(12340)) # [1] TRUE # 案例2:530与570,取整到十位后不相等 verify_rounded_equal(c(530), c(570)) # [1] FALSE # 案例3:0.076与0.0762,取整到千分位后相等 verify_rounded_equal(c(0.076), c(0.0762)) # [1] TRUE
内容的提问来源于stack exchange,提问作者Simon.S.A.
相关产品推荐
相关产品推荐

