使用 Rcpp 将矩阵四舍五入到任意精度
Rounding a matrix to arbitrary precision using Rcpp
我想在 Rcpp 中将矩阵 M
舍入到任意精度。在 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
事实证明,这在 Rcpp / C++ 中有点挑战性。
有一个 round()
函数,但是不幸的是,它只能四舍五入到最接近的整数。出于输出目的,例如"%.2f"
格式可用于四舍五入到两位小数。如果要在进一步计算中使用四舍五入的数字,可以通过使用手动调整的 floorf
、roundf
和 ceilingf
函数将单个元素四舍五入到任意精度,不同的比例因子,请参阅讨论和建议的解决方案 here。
因此,一种可能的前进方式是将上述方法应用于矩阵 M
的每个元素(或更有效地应用于每一列)。这似乎不必要地复杂,我想知道你们中是否有人有更多 efficient/elegant 解决方案,用于在 Rcpp 中将矩阵四舍五入到任意精度。
您可以自己实现,例如
#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
F. Privé 有一个技术上正确的答案。但是,就像他之前的 OP 一样,它错过了 Rcpp 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
参数的 默认值 是 唯一允许的值 为位数。自然不是。
我想在 Rcpp 中将矩阵 M
舍入到任意精度。在 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
事实证明,这在 Rcpp / C++ 中有点挑战性。
有一个 round()
函数,但是不幸的是,它只能四舍五入到最接近的整数。出于输出目的,例如"%.2f"
格式可用于四舍五入到两位小数。如果要在进一步计算中使用四舍五入的数字,可以通过使用手动调整的 floorf
、roundf
和 ceilingf
函数将单个元素四舍五入到任意精度,不同的比例因子,请参阅讨论和建议的解决方案 here。
因此,一种可能的前进方式是将上述方法应用于矩阵 M
的每个元素(或更有效地应用于每一列)。这似乎不必要地复杂,我想知道你们中是否有人有更多 efficient/elegant 解决方案,用于在 Rcpp 中将矩阵四舍五入到任意精度。
您可以自己实现,例如
#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
F. Privé 有一个技术上正确的答案。但是,就像他之前的 OP 一样,它错过了 Rcpp 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
参数的 默认值 是 唯一允许的值 为位数。自然不是。