R中数字值的双精度(64位)表示形式(符号,指数,有效位数)

989*_*989 6 floating-point r numeric

R FAQ指出:

唯一可以用R的数字类型精确表示的数字是分母为2的幂的整数和分数。所有其他数字在内部舍入为(通常)53个二进制数字精度。

R使用IEEE 754双精度浮点数,即

  • 1位符号
  • 11位指数
  • 尾数为52位(或有效位数)

总计为64位。

对于数字0.1,R表示

sprintf("%.60f", 0.1)
[1] "0.100000000000000005551115123125782702118158340454101562500000"
Run Code Online (Sandbox Code Playgroud)

Double(IEEE754双精度64位)为我们提供了以下二进制表示形式0.1

00111111 10111001 10011001 10011001 10011001 10011001 10011001 10011010
Run Code Online (Sandbox Code Playgroud)

我们如何在R中获得此表示形式,以及它与sprintf本示例中给出的输出有何关系?

Ral*_*ner 5

@chux在评论中提出的问题的答案是“是”。R支持%a格式:

sprintf("%a", 0.1)
#> [1] "0x1.999999999999ap-4"
Run Code Online (Sandbox Code Playgroud)

如果要访问基础位模式,则必须将double解释为64位整数。为此,可以通过Rcpp使用C ++:

Rcpp::cppFunction('void print_hex(double x) {
    uint64_t y;
    static_assert(sizeof x == sizeof y, "Size does not match!");
    std::memcpy(&y, &x, sizeof y);
    Rcpp::Rcout << std::hex << y << std::endl;
}', plugins = "cpp11", includes = "#include <cstdint>")
print_hex(0.1)
#> 3fb999999999999a
Run Code Online (Sandbox Code Playgroud)

此十六进制表示形式与您的二进制表示形式相同。如何获得小数表示形式?

  • 第一位为零,因此符号为正
  • 指数为0x3fb,即十进制为1019。给定指数偏差,这对应于实际指数-4。
  • 尾数为0x1999999999999a×2 ^ -52,包括隐式1,即2 ^?52×7,205,759,403,792,794。
  • 总共得出2 ^?56×7,205,759,403,792,794:

    sprintf("%.60f", 2^-56 * 7205759403792794)
    #> [1] "0.100000000000000005551115123125782702118158340454101562500000"
    
    Run Code Online (Sandbox Code Playgroud)