sprintf invalid format '%d'

c, coercion, printf, r

Solution

This is actually really interesting question. To start, `%d` stands for integer. The vector argument is recycled if possible but if it is `c(1.5, 1)` it will fail when `sprintf()` tries to replace `%d` with 1.5 (which is not integer).

I thought it might be related to the fact that in R both integer and double are numeric mode, for example:

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"

Thus both vectors should be stored as double. More info about vector in R language definition and in the documentation for `? numeric`:

The potential confusion is that R has used mode "numeric" to mean ‘double or integer’"

I might have found the lines in the underlying C code which explain what is going on:

if(TYPEOF(_this) == REALSXP) {
double r = REAL(_this)[0];
if((double)((int) r) == r)
_this = coerceVector(_this, INTSXP);

This code does the following: If the vector type is `REALSXP` (which means numeric) then convert first member of vector to `double r`. Then cast `r` as integer and then double and if bytes are still same convert whole vector as `INTSXP`. Importantly, this code only checks the first element of a vector; if that element can be coerced to integer, then the whole vector is coerced, otherwise the code gives an error.

To test this hypothesis one could compile R with a custom `sprintf()` where `double r = REAL(_this)[0];` is changed to `double r = REAL(_this)[1];` and test whether `c(1.5, 1)` works now or not.

Problem

This works: ``` > sprintf('%d', c(1, 1.5)) [1] "1" "1" ``` and this doesn't: ``` > 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 ``` Why?

Original source

Related problems