具有四精度计算的Rcpp

时间:2017-02-16 00:59:30

标签: r rcpp

在Rcpp中以数字方式计算以下内容的最佳方法是什么?

exp(-1500)/(exp(-1500)+exp(-1501))

在许多情况下,计算可能需要多次精确(对于exp),但最终结果可以舍入到通常的双倍。

通过四分卫?通过提升?

如果你留在R(在Rcpp之外),那里有非常舒服的包装工作:

library(Rmpfr)

a = mpfr(-1500,100)
b = mpfr(-1501,100)

exp(a)/(exp(a)+exp(b))

但是如何使用rcpp访问?

2 个答案:

答案 0 :(得分:7)

快速启动和运行的方法是安装BH软件包并使用提供several extended precision floating point types的Boost Multiprecision库。例如,此代码演示了float128mpf_float_100类型:

// [[Rcpp::depends(BH)]]
#include <Rcpp.h>
#include <boost/multiprecision/float128.hpp>
#include <boost/multiprecision/mpfr.hpp>

namespace mp = boost::multiprecision;

// [[Rcpp::export]]
std::string qexp(double da = -1500.0, double db = -1501.0)
{
    mp::float128 a(da), b(db);
    mp::float128 res = mp::exp(a) / (mp::exp(a) + mp::exp(b));
    return res.convert_to<std::string>();
}

// [[Rcpp::export]]
std::string mpfr_exp(double da = -1500.0, double db = -1501.0)
{
    mp::mpf_float_100 a(da), b(db);
    mp::mpf_float_100 res = mp::exp(a) / (mp::exp(a) + mp::exp(b));
    return res.convert_to<std::string>();
}

后者需要在编译之前添加用于链接到libmpfrlibgmp的标志;前者没有,因为它是GCC内置的__float128

的包装器
Sys.setenv("PKG_LIBS" = "-lmpfr -lgmp")
Rcpp::sourceCpp('/tmp/quadexp.cpp')

qexp()
# [1] "0.731058578630004879251159241821836351"

mpfr_exp()
# [1] "0.731058578630004879251159241821836274365144640165056519276365907919040453070204639387474532075981245292174466493140773"

Rmpfr比较,

library(Rmpfr)

a <- mpfr(-1500, 100)
b <- mpfr(-1501, 100)

exp(a) / (exp(a) + exp(b))
# 1 'mpfr' number of precision  100   bits 
# [1] 7.3105857863000487925115924182206e-1

答案 1 :(得分:1)

我担心你可能会感到困惑。

Rcpp是R和C ++之间的桥梁。它既不是新语言,也不是新系统。

在C ++中,您使用类似GNU gmplib又名 GNU多精度算术库的东西,当然,它已经作为包gmp

但是如果你想编写从R调用的C ++函数,那么就可以连接GMP库。它回溯到如何编写一个可以从R调用的C ++函数来访问外部库&#39; - 这个问题在这里也被多次讨论过了。