我一整天都在考虑它,但仍然无法弄清楚为什么会这样。我的目标很简单:STEP1,生成函数S(h,p);步骤2,通过梯形法则对S(h,p)进行数值积分,得到新函数SS(h)。我编写了代码并通过sourceCpp来源它,它在R中成功生成了两个函数S(h,p)和SS(h)。但是当我尝试通过计算SS(1)来测试它时,R只是保持运行而且从不给出了结果,这很奇怪,因为计算量并不大。知道为什么会这样吗?
我的代码在这里:
#include <Rcpp.h>
using namespace Rcpp;
//generate the first function that gives S(h,p)
// [[Rcpp::export]]
double S(double h, double p){
double out=2*(h+p+h*p);
return out;
}
//generate the second function that gives the numerically integreation of S(h,p) w.r.t p
//[[Rcpp::export]]
double SS(double h){
double out1=0;
double sum=0;
for (int i=0;i<1;i=i+0.01){
sum=sum+S(h,i);
}
out1=0.01/2*(2*sum-S(h,0)-S(h,1));
return out1;
}
答案 0 :(得分:5)
问题在于您正在将i
视为在此声明中不是int
:
for (int i=0;i<1;i=i+0.01){
sum=sum+S(h,i);
}
在每次迭代之后,您尝试将0.01
添加到一个整数,当然会立即将其截断为0,这意味着i
总是等于零,并且您有一个无限循环。一个突出问题的最小例子,有几个可能的解决方案:
#include <Rcpp.h>
// [[Rcpp::export]]
void bad_loop() {
for (int i = 0; i < 1; i += 0.01) {
std::printf("i = %d\n", i);
Rcpp::checkUserInterrupt();
}
}
// [[Rcpp::export]]
void good_loop() {
for (int i = 0; i < 100; i++) {
std::printf("i = %d\n", i);
Rcpp::checkUserInterrupt();
}
}
// [[Rcpp::export]]
void good_loop2() {
for (double j = 0.0; j < 1.0; j += 0.01) {
std::printf("j = %.2f\n", j);
Rcpp::checkUserInterrupt();
}
}
第一个替代方法(good_loop
)是适当地缩放步长 - 从0到99循环1需要相同的迭代次数,循环次数从0到0.99乘以0.01。此外,您可以使用double
代替int
,例如good_loop2
。无论如何,这里的主要内容是你需要更加谨慎地选择C ++中的变量类型。与R不同,当您将i
声明为int
时,它将被视为int
,而不是浮点数。
答案 1 :(得分:0)
正如@nrussell非常熟练地指出的那样,当持有的类型为i
时,将int
视为double
存在问题。发布此答案的目的是强调需要避免使用double
或float
作为循环增量器。我选择将其作为答案发布而不是评论可读性。
请注意,由于精度问题,循环增量应 不 作为double
或float
。例如自i = .99
以后...... {/ p>很难得到i = 0.981111111
相反,我会选择将循环作为int
进行处理,并尽快将其转换为double
/ float
,例如
for (int i=0; i < 100; i++){
// Make sure to use double division
// (e.g. either numerator or denominator is a floating / double)
sum += S(h, i/100.0);
}
补充说明: