(Rcpp)armadillos abs() 函数在与 c++ double 一起使用时输出错误值,而 std::abs 有效
(Rcpp)armadillos abs() function outputs false values when used with c++ double while std::abs works
考虑这个 R 函数:
r_abs <- function(x,y,z){
2 * abs((x >= y) - z)
}
还有那 2 个 RcppArmadillo 等价物:
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::depends(RcppProgress)]]
#include <RcppArmadillo.h>
#include <string>
#include <progress.hpp>
using namespace arma;
// [[Rcpp::export]]
double arma_abs(const double &x, const double &y, const double &z)
{
return 2 * abs((x >= y) - z);
}
// [[Rcpp::export]]
double std_abs(const double &x, const double &y, const double &z)
{
return 2 * std::abs((x >= y) - z);
}
问题来了:
sourceCpp(".test/test.cpp")
x <- 1
y <- 2
z <- 0.5
r_abs(x,y,z)
[1] 1
arma_abs(x, y, z)
[1] 0
std_abs(x, y, z)
[1] 1
这里为什么arma_abs()输出0?该问题仅出现在 -1 < z < 1
.
非常感谢您提供的任何帮助。
这是 C 和 C++ 的一个棘手且有些乏味的问题 已由最近添加的更正 std::abs()
部分修复。
如果您使用的是 Unix 系统,请尝试 man 3 abs
。您对(不合格)abs()
的使用等同于 ::abs()
并且它从 stdlib.h
.
得到 int abs(int)
并且转换为 int
使参数 -0.5 截断为零,乘以 2 仍为零。简而言之,arma
与此无关。 (而犰狳通常只有它的向量、矩阵、立方体……类型的函数,而不是像 double
这样的原子 C/C++ 类型)。
为了完整起见,我的代码版本在下面嵌入了 R 部分。我删除了未使用的引用 RcppProgress。
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
//using namespace arma;
// [[Rcpp::export]]
double arma_abs(const double &x, const double &y, const double &z) {
auto val = (x >= y) - z;
Rcpp::Rcout << "val " << val << std::endl;
Rcpp::Rcout << "int(val) " << int(val) << std::endl;
return 2 * ::abs((x >= y) - z);
}
// [[Rcpp::export]]
double std_abs(const double &x, const double &y, const double &z) {
return 2 * std::abs((x >= y) - z);
}
/*** R
r_abs <- function(x,y,z){
2 * abs((x >= y) - z)
}
x <- 1
y <- 2
z <- 0.5
r_abs(x,y,z) # 1
arma_abs(x, y, z) # 0
std_abs(x, y, z) # 1
*/
编辑: 错别字已更正。上面我写的是std::fabs()
,意思是std::abs()
。 fabs()
是我们总是必须使用的,以避免这里看到的转换为 int
的问题。
考虑这个 R 函数:
r_abs <- function(x,y,z){
2 * abs((x >= y) - z)
}
还有那 2 个 RcppArmadillo 等价物:
// [[Rcpp::depends(RcppArmadillo)]]
// [[Rcpp::depends(RcppProgress)]]
#include <RcppArmadillo.h>
#include <string>
#include <progress.hpp>
using namespace arma;
// [[Rcpp::export]]
double arma_abs(const double &x, const double &y, const double &z)
{
return 2 * abs((x >= y) - z);
}
// [[Rcpp::export]]
double std_abs(const double &x, const double &y, const double &z)
{
return 2 * std::abs((x >= y) - z);
}
问题来了:
sourceCpp(".test/test.cpp")
x <- 1
y <- 2
z <- 0.5
r_abs(x,y,z)
[1] 1
arma_abs(x, y, z)
[1] 0
std_abs(x, y, z)
[1] 1
这里为什么arma_abs()输出0?该问题仅出现在 -1 < z < 1
.
非常感谢您提供的任何帮助。
这是 C 和 C++ 的一个棘手且有些乏味的问题 已由最近添加的更正 std::abs()
部分修复。
如果您使用的是 Unix 系统,请尝试 man 3 abs
。您对(不合格)abs()
的使用等同于 ::abs()
并且它从 stdlib.h
.
int abs(int)
并且转换为 int
使参数 -0.5 截断为零,乘以 2 仍为零。简而言之,arma
与此无关。 (而犰狳通常只有它的向量、矩阵、立方体……类型的函数,而不是像 double
这样的原子 C/C++ 类型)。
为了完整起见,我的代码版本在下面嵌入了 R 部分。我删除了未使用的引用 RcppProgress。
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppArmadillo.h>
//using namespace arma;
// [[Rcpp::export]]
double arma_abs(const double &x, const double &y, const double &z) {
auto val = (x >= y) - z;
Rcpp::Rcout << "val " << val << std::endl;
Rcpp::Rcout << "int(val) " << int(val) << std::endl;
return 2 * ::abs((x >= y) - z);
}
// [[Rcpp::export]]
double std_abs(const double &x, const double &y, const double &z) {
return 2 * std::abs((x >= y) - z);
}
/*** R
r_abs <- function(x,y,z){
2 * abs((x >= y) - z)
}
x <- 1
y <- 2
z <- 0.5
r_abs(x,y,z) # 1
arma_abs(x, y, z) # 0
std_abs(x, y, z) # 1
*/
编辑: 错别字已更正。上面我写的是std::fabs()
,意思是std::abs()
。 fabs()
是我们总是必须使用的,以避免这里看到的转换为 int
的问题。