这有效:
> sprintf('%d', c(1, 1.5))
[1] "1" "1"
而这不是:
> 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
为什么?
答案 0 :(得分:9)
这实际上是一个非常有趣的问题。首先,%d
代表整数。如果可能,vector参数将被回收,但如果它是c(1.5, 1)
,则sprintf()
尝试将%d
替换为1.5(非整数)时将失败。
我认为这可能与以下事实有关:在R中,整数和双数都是数字模式,例如:
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"
因此两个向量都应该存储为double。有关R language definition中的向量以及? numeric
的文档的更多信息:
潜在的混淆是R使用“数字”模式来表示“双重或整数”“
我可能在the underlying C code中找到了解释发生了什么的行:
if(TYPEOF(_this) == REALSXP) {
double r = REAL(_this)[0];
if((double)((int) r) == r)
_this = coerceVector(_this, INTSXP);
此代码执行以下操作:如果向量类型为REALSXP
(表示数字),则将向量的第一个成员转换为double r
。然后将r
转换为整数然后加倍,如果字节仍然相同,则将整个向量转换为INTSXP
。重要的是,此代码仅检查向量的第一个元素;如果该元素可以强制转换为整数,则整个向量被强制转换,否则代码会产生错误。
为了测试这个假设,可以使用自定义sprintf()
编译R,其中double r = REAL(_this)[0];
更改为double r = REAL(_this)[1];
并测试c(1.5, 1)
现在是否有效。