在 R 中使用整数值代替数值(例如 1L 与 1)作为常量的好处

Tho*_*mas 16 integer interactive r function numeric

在 R 源代码中,大多数(但不是全部)函数使用整数值作为常量:

colnames <- function(x, do.NULL = TRUE, prefix = "col")
{
    if(is.data.frame(x) && do.NULL)
    return(names(x))
    dn <- dimnames(x)
    if(!is.null(dn[[2L]]))
    dn[[2L]]
    else {
        nc <- NCOL(x)
    if(do.NULL) NULL
        else if(nc > 0L) paste0(prefix, seq_len(nc))
        else character()
    }
}
Run Code Online (Sandbox Code Playgroud)

R语言定义说:

在大多数情况下,整数和数值之间的差异并不重要,因为 R 在使用数字时会做正确的事情。然而,有时我们想显式地为常量创建一个整数值。

  • 在哪些情况下需要强制常量使用整数值而不是简单地使用数值?例如,例如 1 会失败,但例如 1L 不会失败的示例是受欢迎的。
  • 相反,在哪些情况下不需要使用整数值(例如交互式使用与编程、使用常量索引等)?

问题是关于良好实践和基本原理,而不是关于“L”符号本身整数类和数字类之间的差异比较数字

nic*_*ola 13

L这些是我在声明常量时显式使用后缀的一些用例。当然,这些并不是严格的“规范”(或唯一的),但也许您可以了解背后的基本原理。我为每种情况添加了一个“必要”标志;您会发现,仅当您与其他语言(如 C)交互时,这些才会出现。

  • 逻辑类型转换(非必须)

as.integer我没有使用经典的,而是使用添加0L到逻辑向量来使其成为整数。当然,您可以只使用0,但这需要更多内存(通常是 8 字节而不是 4 字节)和转换。

  • 操作返回整数的函数的结果(不必要)

举例来说,您想要 find 来检索 a 之后的向量元素NA。你可以:

which(is.na(vec)) + 1L
Run Code Online (Sandbox Code Playgroud)

由于which返回一个integer,添加1L将保留类型并避免隐式转换。如果省略 则不会发生任何事情L,因为这只是一个小的优化。例如,这种情况也会发生match:如果您想对此类函数的结果进行后处理,那么如果可能的话,保留类型是一个好习惯。

  • 接口C(必要)

?integer

整数向量的存在使得数据可以传递到需要它们的 C 或 Fortran 代码,并且可以精确而紧凑地表示(小)整数数据。

C 对于数据类型更加严格。这意味着,如果将向量传递给 C 函数,则不能依赖 C 来进行转换。假设您想用某个值替换 NA 之后的元素,例如 42。您可以在 R 级别找到 NA 值的位置(就像我们之前对 所做的那样which),然后将原始向量和索引向量传递给 C .C 函数将如下所示:

SEXP replaceAfterNA (SEXP X, SEXP IND) {
   ...
   int *ind = INTEGER(IND);
   ...
   for (i=0; i<l; i++) {
        //make here the replacement
   }
}
Run Code Online (Sandbox Code Playgroud)

和从 R 侧:

...
ind <- which(is.na(x)) + 1L
.Call("replaceAfterNA", x, ind)
...
Run Code Online (Sandbox Code Playgroud)

如果省略L上面第一行中的 ,您将收到如下错误:

INTEGER() cannot be applied to double vectors
Run Code Online (Sandbox Code Playgroud)

因为 C 需要整数类型。

  • Java接口(必要)

和之前一样。如果您使用该rJava包并希望 R 调用您自己的自定义 Java 类和方法,则必须确保当 Java 方法需要整数时传递整数。这里不添加具体示例,但应该清楚为什么L在这些情况下您可能希望在常量中使用后缀。

附录

前面的案例说明了您何时可能想要使用L. 即使我猜想不太常见,添加一个您想要L. 如果存在整数溢出的危险,则可能会出现这种情况。如果两个操作数都是整数,则*,+和运算符会保留类型。-例如:

#this overflows
31381938L*3231L
#[1] NA
#Warning message:
#In 31381938L * 3231L : NAs produced by integer overflow

#this not
31381938L*3231
#[1] 1.01395e+11
Run Code Online (Sandbox Code Playgroud)

因此,如果您对可能产生溢出的整数变量进行操作,则必须将其强制转换double以避免任何风险。向该变量添加/减去一个不带 的常量L可能是进行强制转换的好机会。