【问题标题】:R numeric to char precision lossR numeric to char 精度损失
【发布时间】:2018-11-13 11:03:03
【问题描述】:

我想将我的多位数字向量转换为字符。我尝试了以下解决方案here,它适用于一个数字,但不适用于向量。没关系

options(digits=20)
options(scipen=99999)
x<-129483.19999999999709;format(round(x, 12), nsmall = 12)
[1] "129483.199999999997"

但事实并非如此。如何保持数字向量字符的数字精度?

> y <- c(129483.19999999999709, 1.3546746874,687676846.2546746464)

特别有问题的是687676846.2546746464 也试过了:

> specify_decimal(y, 12)
[1] "129483.199999999997"    "1.354674687400"         "687676846.254674673080"
> formatC(y, digits = 12, format = "f")
[1] "129483.199999999997"    "1.354674687400"         "687676846.254674673080"
> formattable(y, digits = 12, format = "f")
[1] 129483.199999999997    1.354674687400         687676846.254674673080
> sprintf(y, fmt='%#.12g')
[1] "129483.200000" "1.35467468740" "687676846.255"
> sprintf(y, fmt='%#.22g')
[1] "129483.1999999999970896" "1.354674687399999966075" "687676846.2546746730804"

预期结果:

[1] "129483.199999999997" "1.354674687400" "687676846.254674646400"

好像精度损失只发生一次,不会重复。

> require(dplyr)
> convert <- function(x) as.numeric(as.character(x))
> 687676846.2546746464 %>% convert
[1] 687676846.25467503
> 687676846.2546746464 %>% convert %>% convert %>% convert
[1] 687676846.25467503

这里我只有 5 位数的精度,但更成问题的是我无法事先知道我将获得什么精度..

【问题讨论】:

  • as.numeric(as.character(129483.123456789)) == 129483.123456789 打印出TRUE。我认为这里有两个问题。首先,打印到控制台的内容可能无法反映潜在的精度。其次,您的样本数是浮点数,并且由于舍入误差可能存在一些问题。如果您查看我的示例编号,则四舍五入不会有问题。
  • 好吧,我的号码呢?
  • 字符串一定要显示所有数字
  • 在这里查看:stackoverflow.com/questions/3443687/…,我认为这段代码可以满足您的需求:x&lt;-129483.19999999999709;format(round(x, 14), nsmall = 14)
  • 如果您这样做是因为您想将数字写入文本文件,以便在读取文本文件时可以恢复完全相同的数字,也许您可​​以将其转换为二进制表示(缩写为 hex)。

标签: r type-conversion precision


【解决方案1】:

最后,我可以使用这些功能做我想做的事。 addtrailingzeroes 将在 x 后添加多个零。

nbdec <- function(x) {
  x1 <- as.character(x)
  xsplit <- strsplit(x1,"\\.")
  xlength <- sapply(xsplit, function(d) nchar(d)[2])
  xlength <- ifelse(is.na(xlength), 0, xlength)
  return(xlength)
}

trailingzeroes <- function(x, dig) {
  res <- rep(NA, length(x))
  for( i in 1:length(x)) {
    if(!is.na(x[i])) res[i] <- { paste0(rep(0,max(0,dig-nbdec(x[i]))), collapse="") }
    else { res[i] <- ""}
    }
return(res)
}

trailingcommas <- function(x) ifelse(is.na(x), NA, ifelse(nbdec(x)==0, ".",""))

addtrailingzeroes <- function(x, digits) {
  return(ifelse(!is.na(x), paste0(x, trailingcommas(x), trailingzeroes(x, digits)),NA))
}

但是为了抑制不准确和舍入错误,必须首先使用 roundnumerics.max 裁剪 x:

roundnumerics.max <- function(df, startdig=12) {
  for(icol in 1:ncol(df)) {
    if( is.numeric(df[,icol])) {
      dig <- startdig
      while(any(!as.numeric(as.character(df[,icol])) %==% df[,icol])) {
        dig <- dig-1
        df[,icol] <- round(df[,icol], digits=dig)
        if(dig==0) {
          break
          pprint("ERROR: zero numeric accuracy")
        }
      } 
      pprint("Numeric accuracy for column ",icol," ", colnames(df)[icol], " is ", dig)
    }
  }
  return(data.frame(df, stringsAsFactors = F))
}

这很慢而且远非优雅......我仍然认为很难相信 R 对 16 位有效数字有如此精确的限制,并且添加了不准确的噪音,当你尝试增加digits 选项...让您知道...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-13
    • 1970-01-01
    • 2020-07-28
    • 2015-04-26
    • 1970-01-01
    • 1970-01-01
    • 2016-12-19
    相关资源
    最近更新 更多