RcppArmadillo and C++ division issue

一笑奈何 提交于 2019-12-12 06:32:07

问题


A very simple question regarding RcppArmadillo. Trying to multiply a vector by a scalar, and getting different results depending on small changes in syntax.

Any ideas?

// [[Rcpp::depends("RcppArmadillo")]]
// [[Rcpp::export]]
arma::vec funtemp(arma::vec x)              
{
  // return(x/10); // this works
  // return((1/10)*x); // this does not work 
  return(x*(1/10)); // this does not work
}

回答1:


Ahh, the good ol' integer vs. double division problem in C++. Before we begin, note that: arma::vec is by default a double and 1, 10, 1/10 are all ints...

Let's take a look at your functions separately:

#include <RcppArmadillo.h>

// [[Rcpp::depends("RcppArmadillo")]]

// [[Rcpp::export]]
arma::vec funtemp_one(arma::vec x)
{
  return(x/10); // this works
}

// [[Rcpp::export]]
arma::vec funtemp_two(arma::vec x)
{
  return((1/10)*x);  // this does not work
}

// [[Rcpp::export]]
arma::vec funtemp_three(arma::vec x)
{
  return(x*(1/10)); // this does not work
}

Therefore, when we run through your problem we get:

> funtemp_one(1)
     [,1]
[1,]  0.1

> funtemp_two(1)
     [,1]
[1,]    0

> funtemp_three(1)
     [,1]
[1,]    0

In the later functions (e.g. the 1/10), the operator/ that is being used is int based division. As a result, 2 ints enter and 1 int is returned. If the result is not divisible, then you end up with a zero being returned as it is outside of the integer scope.

In order to use the double version, which returns a double, at least one of the ints must be explicitly cast to a double. This happens by default in the first case as you have a double/int due to arma::vec's structure. The second and third cases have an int/int structure that can be dealt with in two ways: 1. use a .0 after the int or 2. explicitly cast the value as a double with double(int)

e.g.

// [[Rcpp::export]]
arma::vec funtemp_four(arma::vec x)
{
  return(x*(1/10.0)); // this works
}

// [[Rcpp::export]]
arma::vec funtemp_five(arma::vec x)
{
  return(x*(1/double(10))); // this works
}

Will give what you expect:

> funtemp_four(1)
     [,1]
[1,]  0.1

> funtemp_five(1)
     [,1]
[1,]  0.1


来源:https://stackoverflow.com/questions/36986097/rcpparmadillo-and-c-division-issue

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!