【问题标题】:Convert a base2 number (with fractional part) to a base10 number in R?将基数为 2 的数字(带小数部分)转换为 R 中的基数为 10 的数字?
【发布时间】:2019-10-18 13:28:21
【问题描述】:

如何在 R 中将 base2 数(带小数部分)转换为 base10 数?该数字也可以是负数。

例子:

from2to10(10100101) # "165"
from2to10(0) # "0"
from2to10(10100101.01) # "165.25"
from2to10(-10100101) # "-165"
from2to10(-10100101.01) # "-165.25"
from2to10(111101111.010111) # "495.359375"

【问题讨论】:

    标签: r binary decimal data-conversion base


    【解决方案1】:

    编辑:我意识到我假设输入是character,这对我来说可能是一个错误的假设。我相信相信 R 来保存你所有的 0 和 1(考虑到 R FAQ 7.31)有点信任,但我会保持原样,除非/直到出现更好的情况。


    这很有趣...不确定是否有处理非十进制浮点数的 R 函数,所以这里有一个 ...

    #' Convert floating-point binary to decimal
    #'
    #' @param s 'character'
    #' @return 'numeric'
    #' @examples
    #' tests <- c("10100101", "0", "10100101.01", "-10100101", "-10100101.01", "111101111.010111")
    #' base2float(tests)
    #' # [1]  165.0000    0.0000  165.2500 -165.0000 -165.2500  495.3594
    base2float <- function(s, base = 2L) {
      # ensure the strings seem logical:
      # - start with "-", "+", or "[01]"
      # - zero or more "[01]"
      # - optional decimal "." (can easily change to "," for alternate reps)
      # - zero or more "[01]"
      stopifnot(all(grepl("^[-+]?[01]*\\.?[01]*$", s)))
      splits <- strsplit(s, "\\.")
      wholes <- sapply(splits, `[[`, 1L)
      wholes[wholes %in% c("", "-", "+")] <- paste0(wholes[wholes %in% c("", "-", "+")], "0")
      fracs <- sapply(splits, `[`, 2L)
      fracs[is.na(fracs)] <- "0"
      # because string-length is used in our calcs ...
      fracs <- gsub("0+$", "0", fracs)
      whole10 <- strtoi(wholes, base = base)
      frac10 <- strtoi(fracs, base = base) / (base^nchar(fracs))
      whole10 + sign(whole10)*frac10
    }
    
    

    【讨论】:

    • base2float("111101111.010111")=495.3594 &lt;&gt; "495.359375"=from2to10(111101111.010111) 差异可以忽略不计。 base2float("0.001")=0 &lt;&gt; "0.125"=from2to10(0.001)。因此,base2float 在打印结果时可能会进行微调。
    • 如果您的 options("digits") 告诉它,它只会产生 0.3594。 (使用options(digits=8),它产生更接近的495.35938。在这种情况下,函数是正确的,控制台上的表示应该归咎于明显的,而不是实际的差异。 )
    • base2float("111101111.010111") == (strtoi("111101111", 2) + 1/4 + 1/16 + 1/32 + 1/64) 是真的。
    • 我现在学会了更改options("digits") 来控制实际/表观差异,以及strtoi。即使从您的 cmets 中,也可以学到很多东西。非常感谢。
    • 另外,[这里] (stackoverflow.com/questions/56411025/…),一位用户 (martin_joerg) 找到了一个解决方案,即从数字到数字。
    【解决方案2】:
    library(cwhmisc) # int, frac
    from2to10 <- function(n) {
    SignOfNumber <- ""
    if (n < 0) {
    n <- abs(n)
    SignOfNumber <- "-"}
    
    nWhole <- int(n)
    nWhole <- as.character(nWhole)
    
    nFraction <- frac(n)
    nFraction <- as.character(nFraction)
    
    DecimalWhole   <- sapply(strsplit(nWhole, split=""), function(x) sum(as.numeric(x) * 2^(rev(seq_along(x) - 1))))
    
    if (nFraction == 0) {
    DecimalFraction <- ""
    paste0(SignOfNumber, DecimalWhole)
    } else { # Find decimal fraction part
    
    part3 <- function(x, y, z) { eval(parse(text=(paste(x, y, z,sep="")))) }
    y <- as.numeric(strsplit(substr(part3("\"",n,"\""), which(strsplit(part3("\"",n,"\""), "")[[1]]==".") + 1, nchar(part3("\"",n,"\""))),"")[[1]])
    DecimalFraction <- sum(y * (0.5^(1:length(y))))
    paste0(SignOfNumber, DecimalWhole + DecimalFraction)
    }
    }
    
    from2to10(10100101) # "165"
    from2to10(0) # "0"
    from2to10(10100101.01) # "165.25"
    from2to10(-10100101) # "-165"
    from2to10(-10100101.01) # "-165.25"
    from2to10(111101111.010111) # "495.359375"; numeric to string; exact conversion
    base2float("111101111.010111") # 495.3594; string to numeric; conversion with rounding. (r2evans)
    

    【讨论】:

    • paste 没有给出 “R 中的 base10 数”,也许你应该重申你的期望
    • @r2evans 你是对的。但是,当我使用as.numeric(from2to10(111101111.010111)) # [1] 495.3594 时,它会四舍五入,并且找不到确切的值 495.359375。所以,我没有将as.numeric( paste0(...) ) 放在函数体中。如果我能找到防止舍入的方法,我会把它放在函数的主体中。此外,数字到数字将是粘贴中的克丽玛 :)
    • 如果你定义一个不带引号的浮点数,那么它是numeric base 10。我不知道 R FAQ-7.31 的解决方法,这意味着你可能会(没有hackery)通常(并非总是)存在差异,您会在数据中找到非 0/1。你从哪里得到这些“数字”,使得(1)你知道它们不是以 10 为底的,但(2)R 认为它们是数字?也许您应该回到那个阶段并“鼓励” R 将它们读入字符串,而不是数字。这样可能会更好。 (然后你可以使用我的功能:-)
    • 如果你定义一个不带引号的浮点数,那么它就是以 10 为底的数字:现在,我明白你为什么要从字符串转为数字了。我以前没有想到这一点。你是 100% 正确的。我也会回答您评论的其余部分。
    • 我明白,而且它很少像关于 SO 的问题/答案那么简单。通常,质疑假设可以帮助我们发现更简单的解决方案,有时允许更优雅/弹性/健壮的解决方案,或者,缺少这些,更少问题的黑客攻击。祝你好运!
    猜你喜欢
    • 1970-01-01
    • 2021-10-15
    • 1970-01-01
    • 2021-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 1970-01-01
    相关资源
    最近更新 更多