c++ - 使用 Rcpp,如何计算两个大复数的比率
问题描述
我正在使用 R,并且我有一个复数分数:
library(pracma);
sigma.jj = 1;
si = 2+3i;
N = 2*exp( 0.5*(- (sigma.jj^2)*(si^2)) ); # 23.39454+6.80796i
D = 1-pracma::erfz( (2^(-0.5))* ( si*sigma.jj )); # 2.225013-1.597002i
N/D; # 5.489974+7.000163i
请注意,我正在调用erfz
...复杂的错误函数。这是该pracma
函数库的源代码:
# Complex error function
erfz <- function(z)
{
if (is.null(z)) return( NULL )
else if (!is.numeric(z) && !is.complex(z))
stop("Argument 'z' must be a numeric or complex scalar or vector.")
a0 <- abs(z)
c0 <- exp(-z * z)
z1 <- ifelse (Re(z) < 0, -z, z)
i <- a0 <= 5.8
work.i <- i
cer <- rep(NA, length = length(z))
if ( sum(work.i) > 0) {
cs <- z1
cr <- cs
for (k in 1:120) {
cr[work.i] <- cr[work.i] * z1[work.i] * z1[work.i]/(k + 0.5)
cs[work.i] <- cs[work.i] + cr[work.i]
work.i <- work.i & (abs(cr/cs) >= 1e-15)
if (sum(work.i) == 0) break
}
cer[i] <- 2 * c0[i] * cs[i]/sqrt(pi)
}
work.i <- !i
if( sum(work.i) > 0) {
cl <- 1/z1
cr <- cl
for (k in 1:13) {
cr[work.i] <- -cr[work.i] * (k - 0.5)/(z1[work.i] * z1[work.i])
cl[work.i] <- cl[work.i] + cr[work.i]
work.i <- work.i & (abs(cr/cl) >= 1e-15)
if (sum(work.i) == 0) break
}
cer[!i] <- 1 - c0[!i] * cl[!i]/sqrt(pi)
}
cer[ Re(z) < 0] <- -cer[ Re(z) < 0]
return(cer)
}
您会注意到每个的 N 和 D 都在变大,但比例N/D
保持相对可控。
sigma.jj = 1;
si = 2+13i;
N = 2*exp( 0.5*(- (sigma.jj^2)*(si^2)) ); # 8.73323e+35-1.029433e+36i
D = 1-pracma::erfz( (2^(-0.5))* ( si*sigma.jj )); # -2.692745e+34-3.114988e+34i
N/D; # 5.04326+32.39578i
在某些时候,R 中断:
sigma.jj = 1;
si = 2+33i;
N = 2*exp( 0.5*(- (sigma.jj^2)*(si^2)) ); # -8.046987e+235+2.13732e+234i
D = 1-pracma::erfz( (2^(-0.5))* ( si*sigma.jj )); # -3.31367e+232+9.716936e+233i
N/D; # 5.01787+82.64292i
现在它打破了:
sigma.jj = 1;
si = 2+38i;
N = 2*exp( 0.5*(- (sigma.jj^2)*(si^2)) ); # Inf-Infi
D = 1-pracma::erfz( (2^(-0.5))* ( si*sigma.jj )); # NaN-Infi
N/D; # NaN+NaNi
所以我相信我可以插入一些可以执行此计算的 C++ 库。由于复杂的误差函数,分子可能比分母更容易。
我之前在 R 中包含了独立的 C++ 代码,使用此链接作为指南:fast large matrix multiplication in R
就像是:
// [[Rcpp::depends(RcppArmadillo, RcppEigen)]]
#include <RcppArmadillo.h>
#include <RcppEigen.h>
// [[Rcpp::export]]
SEXP armaMatMult(arma::mat A, arma::mat B){
arma::mat C = A * B;
return Rcpp::wrap(C);
}
// [[Rcpp::export]]
SEXP eigenMatTrans(Eigen::MatrixXd A){
Eigen::MatrixXd C = A.transpose();
return Rcpp::wrap(C);
}
// [[Rcpp::export]]
SEXP eigenMatMult(Eigen::MatrixXd A, Eigen::MatrixXd B){
Eigen::MatrixXd C = A * B;
return Rcpp::wrap(C);
}
// [[Rcpp::export]]
SEXP eigenMapMatMult(const Eigen::Map<Eigen::MatrixXd> A, Eigen::Map<Eigen::MatrixXd> B){
Eigen::MatrixXd C = A * B;
return Rcpp::wrap(C);
}
我希望对 Numerator 有所帮助,这似乎是一个很大的数字,所以一个允许这样做的库。
对于分母,也可以处理大数,但可以访问erfz
C++ 库中的函数。
然后我可以使用 Rcpp 获取它
library(Rcpp)
sourceCpp("multiply.cpp")
如何将分子中的大复数相乘(并取指数)?如何在分母中多重化和应用复杂的误差函数?
也许每个功能?
https://www.tutorialspoint.com/handling-large-numbers-in-cplusplus
https://www.tutorialspoint.com/cpp_standard_library/complex.htm
https://en.cppreference.com/w/cpp/numeric/math/erf
我熟悉 gmp https://gmplib.org/,但不希望不必实现整个库。我也不知道它是否能满足我的需要。
解决方案
推荐阅读
- php - 如何在 laravel 7 中使用自定义表进行身份验证/登录?
- r - 隐藏绘图工具提示颜色痕迹
- jenkins - 如何计算和跟踪从父项目触发的构建状态
- javascript - 检查给定数字是否属于右侧封闭的区间的JS函数
- android - 房间数据库 - 检查数据是否已存在错误
- dart - 如何在 Dart 中将整数作为输入?
- vue.js - 在商店中存储引导切换
- c# - 如何调用方法或将标签从指定类更新为指定类
- java - 消息在发送到 MQ 的消息中包含转义字符,并在转换为 JSON 时导致异常
- jwt - 检索 API 数据 Microsoft Health Bot - 授权错误 JWT 验证失败