Округление матрицы до произвольной точности с использованием Rcpp - PullRequest
0 голосов
/ 25 января 2020

Я бы хотел округлить матрицу M с произвольной точностью в R cpp. Это особенно легко сделать в R:

M <- matrix(rnorm(4), 2, 2)
M
           [,1]      [,2]
[1,] 0.04463484 0.1455878
[2,] 1.77416096 1.0787835

round(M,2)
     [,1] [,2]
[1,] 0.04 0.15
[2,] 1.77 1.08

Это оказывается немного сложным в R cpp / C ++.

Существует функция round(), однако она, к сожалению, округляет только до ближайшего целого числа. Для целей вывода, например, формат "%.2f" может использоваться для округления до двух десятичных знаков. Если округленные числа должны использоваться в дальнейших вычислениях, можно округлить один элемент с произвольной точностью, играя с функциями floorf, roundf и ceilingf, используя вручную настроенные различные коэффициенты масштабирования, см. Обсуждение и предлагаемые решения здесь .

Следовательно, возможный путь продвижения вперед заключается в применении вышеупомянутого подхода к каждому элементу (или более эффективно к каждому столбцу) матрицы M. Это кажется излишне сложным, и мне было интересно, есть ли у кого-нибудь из вас более эффективное / элегантное решение для округления матриц с произвольной точностью в R cpp.

Ответы [ 2 ]

4 голосов
/ 26 января 2020

F. У Приве есть технически правильный ответ. Но он, так же как и ОП до него, упустил, что функция R cpp Sugar уже делает точно то же самое:

R> Rcpp::cppFunction("NumericVector mr(NumericVector x,int d) {return round(x,d);}")
R> set.seed(42)    
R> x <- runif(5)     
R> x    
[1] 0.914806 0.937075 0.286140 0.830448 0.641746     
R> mr(x, 2)    
[1] 0.91 0.94 0.29 0.83 0.64     
R> mr(x, 0)          
[1] 1 1 0 1 1          
R> mr(x, 7)        
[1] 0.914806 0.937075 0.286139 0.830448 0.641745   
R>  

Путаница, если таковая вообще была, заключалась в том, что по умолчанию значение аргумента digits было только допустимым значением для количества цифр. Естественно, это не так.

2 голосов
/ 26 января 2020

Вы можете реализовать это самостоятельно, например,

#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
NumericVector myround(const NumericVector& A, int digits = 0) {
  NumericVector B = clone(A);
  std::size_t K = A.size();
  for (std::size_t k = 0; k < K; k++) {
    B[k] = ::Rf_fround(A[k], digits);
  }
  return B;
}

В R:

> (x <- runif(10))
 [1] 0.5050331 0.8921151 0.4566404 0.5828360 0.6931808 0.9296267 0.3091896 0.4077148 0.9563310
[10] 0.6905403
> myround(x)
 [1] 1 1 0 1 1 1 0 0 1 1
> myround(x, 2)
 [1] 0.51 0.89 0.46 0.58 0.69 0.93 0.31 0.41 0.96 0.69
> (M <- matrix(rnorm(4), 2, 2))
           [,1]     [,2]
[1,] -1.0852162 1.793925
[2,] -0.1912413 1.170089
> myround(M, 2)
      [,1] [,2]
[1,] -1.09 1.79
[2,] -0.19 1.17
...