Неверный формат sprintf ‘% d’

Это работает:

> 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 

Зачем?

Это действительно интересный вопрос. Для начала, %d обозначает целое число. Если возможно, векторный аргумент перерабатывается, но если он 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" 

Таким образом, оба вектора должны храниться как двойные. Больше информации о векторе в определении языка R и в документации для ? numeric ? numeric :

Потенциальная путаница заключается в том, что R использовал режим «числовой» для обозначения «двойное или целое число» »

Я мог бы найти строки в базовом C-коде, которые объясняют, что происходит:

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

Этот код делает следующее: Если векторный тип REALSXP (что означает числовое), то преобразовать первый элемент вектора в double r . Затем нарисуйте r как целое, а затем дважды, и если байты все равно будут конвертировать весь вектор, как INTSXP . Важно отметить, что этот код проверяет только первый элемент вектора; если этот элемент может быть принужден к целому числу, тогда весь вектор будет принудительно, иначе код даст ошибку.

Чтобы проверить эту гипотезу, можно скомпилировать R с помощью специального sprintf() где double r = REAL(_this)[0]; изменяется на double r = REAL(_this)[1]; и проверить, работает ли c(1.5, 1) сейчас или нет.