【问题标题】:finding the number of significant digits versus digits after decimal in r在 r 中查找有效位数与小数点后的位数
【发布时间】:2018-09-18 16:35:50
【问题描述】:

我想找出一个数字向量中的有效数字的数量,这些数字可以有非常不同的比例。

例如,数字 1000 有 1 个数字; 数字 100 也有 1。数字 1300 有 2。

不要与小数点后的位数混淆,在这两种情况下都等于 0。

【问题讨论】:

  • 到目前为止你尝试过什么?你可能想阅读this
  • 我认为您需要更好地定义“有效数字”对您的意义。看起来您有兴趣删除尾随零并计算所有其他数字。它是否正确?您希望能够容纳十进制数字吗? (另请注意,尾随零不一定不重要。如果不了解测量精度,就不可能知道尾随零是否重要)
  • 我想删除尾随零,并按您所说的计算所有其他数字。如果一个数字有十进制数字,则不应计算尾随零。因此,例如 1003.20 有 5 个有效数字

标签: r decimal significant-digits


【解决方案1】:

我认为这可行。如果你有像 100000 这样的数字,你需要通过设置 options(scipen = 999) 来防止 R 使用像 1e5 这样的科学记数法。另外,在这里您发布您不关心小数点后的数字。在这里我假设你没有带小数点的数字,但如果你有,你可以先做 floor(x)。

x <- c(1000,100,1300, 1234,54334,324,1,1,546,12140465,0,100000,10203,20003,20,102030405060,20)

options(scipen = 999)

sapply(x, function(x) {sum(as.numeric(substring(x, 1: nchar(x), 1:nchar(x))) %in% c(1:9))})

这给出了: [1] 1 1 2 4 5 3 1 1 3 7 0 1 3 2 1 6 1

【讨论】:

  • 10203 通常会被解读为具有五个有效数字。 Omry 似乎对计算不包括尾随零的数字感兴趣。
  • 我不确定我是否理解正确。我的函数确实给出了 3 作为 10203 的结果。我所做的是将 10203 拆分为“1”、“0”、“2”、“0”、“3”,再次将这些数字化,然后检查有多少这些长度为 1 的子串位于数字 c(1:9) 的向量中。所以这确实给出了 TRUE、FALSE、TRUE、FALSE、TRUE,我对这些求和,它返回 3。所以应该没问题吧?
  • 10203 有五个有效数字,因为零都在非零数字之间。 @OmryAtia 正在使用一个工作定义,即只有前导零和尾随零是不重要的。应计算所有其他零。
  • 谢谢,我现在明白了。当我阅读原始问题时,我认为 TS 不想在总和中包含 10203 中的零。
【解决方案2】:

你可以试试

library(tidyverse)
library(stringr)
a <- c(1000,100,1300, 1234,1,0,12140465,1003.02,1003.20,1003.22,0.00001)
tibble(a) %>% 
  mutate(b=format(a, scientific = FALSE)) %>% 
  separate(b, into = c("b1", "b2"), sep = "[.]", remove = F) %>% 
  mutate(b1 = case_when(str_sub(b1, str_length(b1),str_length(b1)) == "0" ~ str_count(b1, "[1-9]"),
                      TRUE ~ str_count(b1, "[0-9]"))) %>% 
  mutate(b2 = str_count(b2, "[1-9]")) %>% 
  mutate(res=b1+b2)
# A tibble: 11 x 5
         a b                   b1    b2   res
     <dbl> <chr>            <int> <int> <int>
 1 1.00e+3 "    1000.00000"     1     0     1
 2 1.00e+2 "     100.00000"     1     0     1
 3 1.30e+3 "    1300.00000"     2     0     2
 4 1.23e+3 "    1234.00000"     4     0     4
 5 1.00e+0 "       1.00000"     1     0     1
 6 0.      "       0.00000"     0     0     0
 7 1.21e+7 12140465.00000       8     0     8
 8 1.00e+3 "    1003.02000"     4     1     5
 9 1.00e+3 "    1003.20000"     4     1     5
10 1.00e+3 "    1003.22000"     4     2     6
11 1.00e-5 "       0.00001"     0     1     1

【讨论】:

  • 不知道有效数字的传统读法是什么。尽管如此,我还是编辑了我的答案。
  • 通常,出现在非零数字之间的任何零都被认为是重要的。所以10203 会有五个有效数字; 01230 会有三个。 en.wikipedia.org/wiki/Significant_figures
【解决方案3】:

我已经稍微调整了this article 中的功能以使其再次工作。所有学分归文章作者所有。该功能可能会有所改进。

代码:

x <- c(1000,100,1300, 1200.1, 12345.67, 12345.670)
sapply(x, FUN = sigdigs)
[1] 1 1 2 5 7 7

功能:

sigdigs <- function(n) {
  i <- 0
  # Check for decimal point is present
  if(length(grep("\\.", as.character(n))) > 0) { # real number
    # Separate integer and fractional parts
    intfrac <- unlist(strsplit(as.character(n), "\\."))
    digstring <- paste(intfrac[1], intfrac[2], sep = "")
    numfigs <- nchar(digstring)
    while(i < numfigs) {
      # Find index of 1st non-zero digit from LEFT
      if(substr(digstring,i+1,i+1) == "0") {
        i <- i + 1
        next
      } else {
        sigfigs <- numfigs - i
        break
      }
    }   
  } else {  # must be an integer      
    digstring <- n
    numfigs <- nchar(digstring)
    while(i < numfigs) {
      # Find index of 1st non-zero digit from RIGHT
      if(substr(digstring, numfigs-i, numfigs-i) == "0") {
        i <- i + 1
        next
      } else {
        sigfigs <- numfigs - i
        break
      }
    }   
  }   
  return(sigfigs)
}

【讨论】:

    【解决方案4】:

    此函数会将向量中的每个值转换为字符值,删除所有前导零、尾随零和小数位,并计算剩余的字符数。它的性能似乎与 phiver 的答案相当。

    sigfigs <- function(x){
      orig_scipen <- getOption("scipen")
      options(scipen = 999)
      on.exit(options(scipen = orig_scipen))
    
      x <- as.character(x)
      x <- sub("\\.", "", x)
      x <- gsub("(^0+|0+$)", "", x)
      nchar(x)
    }
    
    x <- c(1000,100,1300, 1200.1, 12345.67, 12345.670)
    
    sigfigs(x)
    

    注意事项

    此函数返回既不是前导零也不是尾随零的位数。这与有效数字的数量并不完全相同。虽然前导零从不重要,但尾随零可能重要也可能不重要 - 决定它们是否需要一些关于测量精度的知识。我建议阅读有关“重要数字”的 Wikipedia 文章以了解更多详细信息。

    【讨论】:

    • 谢谢本杰明,除了 0.00001 应该是一位数(抱歉之前没有指定)
    • 我很抱歉。在删除尾随和前导零之前需要删除小数点。现在已修复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 2018-10-23
    • 1970-01-01
    • 2016-08-15
    • 2021-07-05
    • 2022-11-22
    相关资源
    最近更新 更多