sprintf无效格式'%d'

pom*_*ber 16 c printf r coercion

这有效:

> sprintf('%d', c(1, 1.5))
[1] "1" "1"
Run Code Online (Sandbox Code Playgroud)

这不是:

> sprintf('%d', c(1.5, 1))
Error in sprintf("%d", c(1.5, 1)) : 
  invalid format '%d'; use format %f, %e, %g or %a for numeric objects
Run Code Online (Sandbox Code Playgroud)

为什么?

Mik*_*nen 10

这实际上是非常有趣的问题.首先,%d代表整数.如果可能,vector参数将被回收,但如果是c(1.5, 1),则在sprintf()尝试替换%d为1.5(非整数)时将失败.

我认为这可能与以下事实有关:在R中,integer和double都是数字模式,例如:

storage.mode(c(1.5, 1))
# [1] "double"
storage.mode(c(1, 1.5))
# [1] "double"
mode(c(1,1.5))
# [1] "numeric"
mode(c(1.5,1))
# [1] "numeric"
Run Code Online (Sandbox Code Playgroud)

因此,两个向量应存储为double.有关R语言定义和文档中的矢量的更多信息? numeric:

潜在的混淆是R使用"数字"模式来表示"双重或整数"

我可能已经在底层的C代码中找到了解释发生了什么的行:

if(TYPEOF(_this) == REALSXP) {
double r = REAL(_this)[0];
if((double)((int) r) == r)
_this = coerceVector(_this, INTSXP);
Run Code Online (Sandbox Code Playgroud)

此代码执行以下操作:如果向量类型是REALSXP(表示数字),则将向量的第一个成员转换为double r.然后转换r为整数然后加倍,如果字节仍然相同,则将整个向量转换为INTSXP.重要的是,此代码仅检查向量的第一个元素; 如果该元素可以强制转换为整数,则强制转换整个向量,否则代码会产生错误.

为了测试这个假设,可以使用自定义编译R,sprintf()其中double r = REAL(_this)[0];更改为double r = REAL(_this)[1];并测试是否c(1.5, 1)现在有效.