【问题标题】:Two vector equal in RcppArmadillo?RcppArmadillo中的两个向量相等?
【发布时间】:2018-10-23 20:26:56
【问题描述】:

在我的函数中,我想通过使用 == 来比较矩阵中的行,但它不起作用。

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
// [[Rcpp::export]]
double accept(arma::mat x){
  int b=x.n_rows;
  arma::vec B(b-1);B.zeros();
  for(int i=0;i<b-1;i++){
    arma::rowvec a1;arma::rowvec a2;
    if(x.row(i)==x.row(i+1)){
      B[i]=0;
    }else{
      B[i]=1;
    }
  }
  double bb;bb=sum(B)/(b-1);
  return(bb);
}

错误信息:

c:/Rtools/mingw_64/bin/g++ -std=gnu++11 -I"C:/Users/songxl/DOCUME~1/R/R-35~1.0RC/include" -DNDEBUG -I. ./inst/include -fopenmp -I"C:/Users/songxl/Documents/R/R-3.5.0rc/library/Rcpp/include" -I"C:/Users/songxl/Documents/R/R-3.5 .0rc/library/RcppArmadillo/include" -I"E:/adptive/block" -O2 -Wall -mtune=generic -c acp.cpp -o acp.o acp.cpp:在函数“双重接受(arma::mat)”中: acp.cpp:10:16: 错误: 无法转换 'arma::operator==(const T1&, const T2&) [with T1 = arma::subview_row; T2 = arma::subview_row;类型名 arma::enable_if2::result = const arma::mtGlue, arma::subview_row, arma::glue_rel_eq> ](((const arma::subview_row)(& arma::Mat::row(arma::uword) [with eT = double; arma::uword = unsigned int](((arma ::uword)(i + 1)))))' 来自 'arma::enable_if2, arma::subview_row, arma::glue_rel_eq> >::result {aka const arma::mtGlue, arma::subview_row, arma ::glue_rel_eq>}' 到 'bool' if(x.row(i)==x.row(i+1)){ ^ make: *** [acp.o] 错误 1

【问题讨论】:

  • 什么不完全有效?你得到一个错误?出乎意料的结果?
  • 是的,我认为问题出在“if(x.row(i)==x.row(i+1))”,但我无法解决
  • 错误消息被截断,如果您向我们展示整个消息可能会有用。
  • 不要使用==,它会使用element wise comparison。要比较整个向量或矩阵并获得一个bool,请使用approx_equal()

标签: c++ rcpp armadillo


【解决方案1】:

看起来相等比较不起作用。 (关于为什么浮点数很难做到这一点,有一个很长的故事,请参阅what every computer scientist should know about floating point。)

所以我改写成sum(abs(diff(a1,a2))) &lt; eps;随意使用不同的 epsilon 值:

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
using namespace Rcpp;
// [[Rcpp::export]]
double accept(arma::mat x){
  int b = x.n_rows;
  arma::vec B(b-1);
  B.zeros();
  for (int i=0;i<b-1;i++){
    arma::rowvec a1 = x.row(i);
    arma::rowvec a2 = x.row(i+1);
    if (sum(abs(a1-a2)) < 1e-8) {
      B[i]=0;
    }else{
      B[i]=1;
    }
  }
  double bb = sum(B) / (b-1);
  return(bb);
}

否则你会非常接近。

【讨论】:

  • 好点,并同意 - 当我写最初的答案时没有想到这一点。
【解决方案2】:

我建议不要使用 Dirk 的缩减技术,而是使用 @mtall 所避开的内置 arma::approx_equal() 函数。

这里的想法是检查这些值是否在由容差定义的 epsilon 邻域内。例如,如果|x − y| ≤ tol,则认为标量xy 相等。

示例实现

#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]

// [[Rcpp::export]]
double accept(arma::mat x){
  int b = x.n_rows;
  arma::vec B = arma::zeros<arma::vec>(b-1);

  for(int i = 0; i < b - 1; ++i){

    bool same_vec = approx_equal(x.row(i), x.row(i+1), "absdiff", 0.002);

    if(same_vec) {
      B[i] = 0;
    } else {
      B[i] = 1;
    }

  }

  double bb = sum(B)/(b-1);

  return bb;
}

测试:

x = matrix(rep(1:10, 2), ncol = 2)
accept(x)
# [1] 1

【讨论】:

  • 这仅仅是对现有答案和评论的重复。
  • @mtall 回复时我已经在输入这个了。除此之外,这段代码更简洁一些,并且包含了一个测试用例。
猜你喜欢
  • 2011-07-10
  • 1970-01-01
  • 1970-01-01
  • 2021-05-23
  • 1970-01-01
  • 2012-12-24
  • 1970-01-01
  • 2021-03-02
  • 1970-01-01
相关资源
最近更新 更多