使用 Rcpp 将矩阵四舍五入到任意精度

Posted

技术标签:

【中文标题】使用 Rcpp 将矩阵四舍五入到任意精度【英文标题】:Rounding a matrix to arbitrary precision using Rcpp 【发布时间】:2020-01-25 16:31:42 【问题描述】:

我想在 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" 格式可用于四舍五入到小数点后两位。如果要在进一步计算中使用四舍五入的数字,可以通过使用手动调整的不同比例因子的floorfroundfceilingf 函数将单个元素四舍五入到任意精度,请参阅讨论并提出解决方案here。

因此,一种可能的前进方式是将上述方法应用于矩阵M 的每个元素(或更有效地应用于每一列)。这似乎不必要地复杂,我想知道你们中的某个人是否有更有效/优雅的解决方案,可以在 Rcpp 中将矩阵四舍五入到任意精度。

【问题讨论】:

您写道“一种可能的前进方式是将上述方法应用于每个元素”,这是一个普遍的事实。没有其他方法。大致来说,each and every Rcpp Sugar 函数最终会下降到对每个元素起作用。它还能如何工作?现在,四舍五入很棘手。刚刚在 r-devel 邮件列表上进行了讨论,R Core 成员 Martin Maechler 刚刚为不同/新方法拆分了一个测试包。因此,您也应该做我们许多人所做的事情:如果您想要/需要不同的行为,请实施它。 Rcpp 是一个工具包。 我知道这可能是浮点数学的一个坏主意,但你不能只定义double round_to_n_places(double&amp; d, int n) return std::round(d * std::pow(10, n))/std::pow(10, n); 【参考方案1】:

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 参数的默认 值是位数的唯一允许值。当然不是。

【讨论】:

啊,对不起。因为OP说它没有实现,所以我认为它没有实现.. 我知道怎么回事。即使在标题中使用 grep 也可能是不完美的(所以我经常在单元测试中使用 grep ;-))。与往常一样,我们可以使用更多/更好的文档。不用担心,也没有暗示伤害。简直值得纠正。 我喜欢这本书:teuder.github.io/rcpp4everyone_en/210_rcpp_functions.html。链接部分提供了 Rcpp 提供的类 R 函数,round() 确实是其中之一。 是的,这是几个不错的贡献资源之一。但是我可以在我的部署机器上 grep 我的源代码或测试,这样通常会更快......【参考方案2】:

您可以使用例如自己实现它

#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

【讨论】:

以上是关于使用 Rcpp 将矩阵四舍五入到任意精度的主要内容,如果未能解决你的问题,请参考以下文章

oralce 将浮点型字段,转为指定精度 并且四舍五入

C#将数字四舍五入为双精度数的任意数字[重复]

如何将双精度格式设置为四舍五入到最接近的美元的货币?

打印没有科学格式的双精度并四舍五入到最接近的整数[关闭]

将string类型转换为decimal为啥会自动四舍五入

C语言中数值转换啥时候需要四舍五入,啥时候不需要?如3.1415926转换成%f就是3.141