Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rcpp精度问题 使用RCPP:考虑R中的以下C++函数 cppFunction('long double statZn_cpp(NumericVector dat, double kn) { double n = dat.size(); // Get total sum and sum of squares; this will be the "upper sum" // (i.e. the sum above k) long double s_upper, s_square_upper; // The "lower sums" (i.e. those below k) long double s_lower, s_square_lower; // Get lower sums // Go to kn - 1 to prevent double-counting in main // loop for (int i = 0; i < kn - 1; ++i) { s_lower += dat[i]; s_square_lower += dat[i] * dat[i]; } // Get upper sum for (int i = kn - 1; i < n; ++i) { s_upper += dat[i]; s_square_upper += dat[i] * dat[i]; } // The maximum, which will be returned long double M = 0; // A candidate for the new maximum, used in a loop long double M_candidate; // Compute the test statistic for (int k = kn; k <= (n - kn); ++k) { // Update s and s_square for both lower and upper s_lower += dat[k-1]; s_square_lower += dat[k-1] * dat[k-1]; s_upper -= dat[k-1]; s_square_upper -= dat[k-1] * dat[k-1]; // Get estimate of sd for this k long double sdk = sqrt((s_square_lower - pow(s_lower, 2.0) / k + s_square_upper - pow(s_upper, 2.0) / (n - k))/n); M_candidate = abs(s_lower / k - s_upper / (n - k)) / sdk; // Choose new maximum if (M_candidate > M) { M = M_candidate; } } return M * sqrt(kn); }') 也可以,下面的R代码基本上复制了C++代码应该使用的方法。它能够得出正确的答案 n = length(dat) s_lower = 0 s_square_lower = 0 s_upper = 0 s_square_upper = 0 for (i in 1:(kn-1)) { s_lower = s_lower + dat[i] s_square_lower = s_square_lower + dat[i] * dat[i] } for (i in kn:n) { s_upper = s_upper + dat[i] s_square_upper = s_square_upper + dat[i] * dat[i] } M = 0 for (k in kn:(n-kn)) { s_lower = s_lower + dat[k] s_square_lower = s_square_lower + dat[k] * dat[k] s_upper = s_upper - dat[k] s_square_upper = s_square_upper - dat[k] * dat[k] sdk = sqrt((s_square_lower - (s_lower)^2/k + s_square_upper - (s_upper)^2/(n-k))/n) M_candidate = sqrt(kn) * abs(s_lower / k - s_upper / (n - k)) / sdk cat('k', k, '\n', "s_lower", s_lower, '\n', 's_square_lower', s_square_lower, '\n', 's_upper', s_upper, '\n', 's_square_upper', s_square_upper, '\n', 'sdk', sdk, '\n', 'M_candidate', M_candidate, '\n\n') if (M_candidate > M) { M = M_candidate } }_C++_R_Rounding_Precision_Rcpp - Fatal编程技术网

Rcpp精度问题 使用RCPP:考虑R中的以下C++函数 cppFunction('long double statZn_cpp(NumericVector dat, double kn) { double n = dat.size(); // Get total sum and sum of squares; this will be the "upper sum" // (i.e. the sum above k) long double s_upper, s_square_upper; // The "lower sums" (i.e. those below k) long double s_lower, s_square_lower; // Get lower sums // Go to kn - 1 to prevent double-counting in main // loop for (int i = 0; i < kn - 1; ++i) { s_lower += dat[i]; s_square_lower += dat[i] * dat[i]; } // Get upper sum for (int i = kn - 1; i < n; ++i) { s_upper += dat[i]; s_square_upper += dat[i] * dat[i]; } // The maximum, which will be returned long double M = 0; // A candidate for the new maximum, used in a loop long double M_candidate; // Compute the test statistic for (int k = kn; k <= (n - kn); ++k) { // Update s and s_square for both lower and upper s_lower += dat[k-1]; s_square_lower += dat[k-1] * dat[k-1]; s_upper -= dat[k-1]; s_square_upper -= dat[k-1] * dat[k-1]; // Get estimate of sd for this k long double sdk = sqrt((s_square_lower - pow(s_lower, 2.0) / k + s_square_upper - pow(s_upper, 2.0) / (n - k))/n); M_candidate = abs(s_lower / k - s_upper / (n - k)) / sdk; // Choose new maximum if (M_candidate > M) { M = M_candidate; } } return M * sqrt(kn); }') 也可以,下面的R代码基本上复制了C++代码应该使用的方法。它能够得出正确的答案 n = length(dat) s_lower = 0 s_square_lower = 0 s_upper = 0 s_square_upper = 0 for (i in 1:(kn-1)) { s_lower = s_lower + dat[i] s_square_lower = s_square_lower + dat[i] * dat[i] } for (i in kn:n) { s_upper = s_upper + dat[i] s_square_upper = s_square_upper + dat[i] * dat[i] } M = 0 for (k in kn:(n-kn)) { s_lower = s_lower + dat[k] s_square_lower = s_square_lower + dat[k] * dat[k] s_upper = s_upper - dat[k] s_square_upper = s_square_upper - dat[k] * dat[k] sdk = sqrt((s_square_lower - (s_lower)^2/k + s_square_upper - (s_upper)^2/(n-k))/n) M_candidate = sqrt(kn) * abs(s_lower / k - s_upper / (n - k)) / sdk cat('k', k, '\n', "s_lower", s_lower, '\n', 's_square_lower', s_square_lower, '\n', 's_upper', s_upper, '\n', 's_square_upper', s_square_upper, '\n', 'sdk', sdk, '\n', 'M_candidate', M_candidate, '\n\n') if (M_candidate > M) { M = M_candidate } }

Rcpp精度问题 使用RCPP:考虑R中的以下C++函数 cppFunction('long double statZn_cpp(NumericVector dat, double kn) { double n = dat.size(); // Get total sum and sum of squares; this will be the "upper sum" // (i.e. the sum above k) long double s_upper, s_square_upper; // The "lower sums" (i.e. those below k) long double s_lower, s_square_lower; // Get lower sums // Go to kn - 1 to prevent double-counting in main // loop for (int i = 0; i < kn - 1; ++i) { s_lower += dat[i]; s_square_lower += dat[i] * dat[i]; } // Get upper sum for (int i = kn - 1; i < n; ++i) { s_upper += dat[i]; s_square_upper += dat[i] * dat[i]; } // The maximum, which will be returned long double M = 0; // A candidate for the new maximum, used in a loop long double M_candidate; // Compute the test statistic for (int k = kn; k <= (n - kn); ++k) { // Update s and s_square for both lower and upper s_lower += dat[k-1]; s_square_lower += dat[k-1] * dat[k-1]; s_upper -= dat[k-1]; s_square_upper -= dat[k-1] * dat[k-1]; // Get estimate of sd for this k long double sdk = sqrt((s_square_lower - pow(s_lower, 2.0) / k + s_square_upper - pow(s_upper, 2.0) / (n - k))/n); M_candidate = abs(s_lower / k - s_upper / (n - k)) / sdk; // Choose new maximum if (M_candidate > M) { M = M_candidate; } } return M * sqrt(kn); }') 也可以,下面的R代码基本上复制了C++代码应该使用的方法。它能够得出正确的答案 n = length(dat) s_lower = 0 s_square_lower = 0 s_upper = 0 s_square_upper = 0 for (i in 1:(kn-1)) { s_lower = s_lower + dat[i] s_square_lower = s_square_lower + dat[i] * dat[i] } for (i in kn:n) { s_upper = s_upper + dat[i] s_square_upper = s_square_upper + dat[i] * dat[i] } M = 0 for (k in kn:(n-kn)) { s_lower = s_lower + dat[k] s_square_lower = s_square_lower + dat[k] * dat[k] s_upper = s_upper - dat[k] s_square_upper = s_square_upper - dat[k] * dat[k] sdk = sqrt((s_square_lower - (s_lower)^2/k + s_square_upper - (s_upper)^2/(n-k))/n) M_candidate = sqrt(kn) * abs(s_lower / k - s_upper / (n - k)) / sdk cat('k', k, '\n', "s_lower", s_lower, '\n', 's_square_lower', s_square_lower, '\n', 's_upper', s_upper, '\n', 's_square_upper', s_square_upper, '\n', 'sdk', sdk, '\n', 'M_candidate', M_candidate, '\n\n') if (M_candidate > M) { M = M_candidate } },c++,r,rounding,precision,rcpp,C++,R,Rounding,Precision,Rcpp,1:不应该使用长双精度,因为R表示双精度类型中的所有数值。使用更精确的类型进行中间计算极不可能带来任何好处,而且更可能导致平台之间出现奇怪的不一致 2:您没有初始化s_upper、s_square_upper、s_lower和s_square_lower。您实际上是在R实现中初始化它们,但是在C++实现中忘记了。 3:小问题,但我会用x*x替换powx,2.0调用。虽然这并不重要 4:这是我的固定方法:您需要用C++调用包含C++命名空间的标准库函数。如果您继续使用它,请注意std::sqrt

1:不应该使用长双精度,因为R表示双精度类型中的所有数值。使用更精确的类型进行中间计算极不可能带来任何好处,而且更可能导致平台之间出现奇怪的不一致

2:您没有初始化s_upper、s_square_upper、s_lower和s_square_lower。您实际上是在R实现中初始化它们,但是在C++实现中忘记了。 3:小问题,但我会用x*x替换powx,2.0调用。虽然这并不重要

4:这是我的固定方法:您需要用C++调用包含C++命名空间的标准库函数。如果您继续使用它,请注意std::sqrt而不是sqrt,std::abs而不是abs,std::pow而不是pow

1:不应该使用长双精度,因为R表示双精度类型中的所有数值。使用更精确的类型进行中间计算极不可能带来任何好处,而且更可能导致平台之间出现奇怪的不一致

2:您没有初始化s_upper、s_square_upper、s_lower和s_square_lower。您实际上是在R实现中初始化它们,但是在C++实现中忘记了。 3:小问题,但我会用x*x替换powx,2.0调用。虽然这并不重要

4:这是我的固定方法:您需要用C++调用包含C++命名空间的标准库函数。如果您继续使用它,请注意std::sqrt而不是sqrt,std::abs而不是abs,std::pow而不是pow


事实上,上面列出的所有拨打statZn_cpp的电话都是0。对于操作系统、编译器和编译器版本,您使用的是什么?我也总是得到0。你能用语言解释一下这个函数应该做什么吗?我目前正在使用Linux发行版,Lubuntu,Ubuntu的另一个版本。我的R版本是3.2.4,我的Rcpp版本是0.12.3。我假设Rcpp使用我的系统编译器,即g++v。5.2.1.,虽然我不知道这个事实,但我从未改变过它。我正在研究一个测试统计,这个函数应该计算它。我很难用语言描述这个统计数据是什么,但我可以提供一些等价的R代码。statZn我在主帖子中添加了更多等效代码,以帮助理解问题。所有额外的代码都得到了正确的答案。事实上,我对上面列出的statZn_cpp的所有调用都得到了0。对于操作系统、编译器和编译器版本,您使用的是什么?我也总是得到0。你能用语言解释一下这个函数应该做什么吗?我目前正在使用Linux发行版,Lubuntu,Ubuntu的另一个版本。我的R版本是3.2.4,我的Rcpp版本是0.12.3。我假设Rcpp使用我的系统编译器,即g++v。5.2.1.,虽然我不知道这个事实,但我从未改变过它。我正在研究一个测试统计,这个函数应该计算它。我很难用语言描述这个统计数据是什么,但我可以提供一些等价的R代码。statZn我在主帖子中添加了更多等效代码,以帮助理解问题。所有的附加代码都能得到正确的答案。它是有效的!非常感谢你!除了初始化一些变量之前我没有做过,但是在从R转换到C++时,这一定是丢失了,可能是缺少名称空间是问题所在。我想Rcpp在默认情况下用于这些函数的任何内容都不应该被信任。@bgoldst您可能需要强调abs处理整数,而fabs处理双精度。然而,std::abs过载,可以同时处理这两个问题。@Coatless谢谢您的评论。老实说,我不确定关于呼叫解决方案的具体情况。这取决于Rcpp公开的名称以及名称空间;例如,它是否包括Mth.H/CMAth/NONE、STDLIB H/CSSTDLB/2,不可能是C++版本和编译器所使用的,RCPP是否定义了自己的包装器/垫片、隐式声明等等。这就是为什么我喜欢用它们的命名空间来限定资格函数调用的原因;你通常不必担心这些复杂的细节。但在这种情况下,你可能是对的。它是有效的!非常感谢你!除了初始化一些变量之前我没有做过,但是在从R转换到C++时,这一定是丢失了,可能是缺少名称空间是问题所在。我想Rcpp在默认情况下用于这些函数的任何内容都不应该被信任。@bgoldst您可能需要强调abs处理整数,而fabs处理doubl
锿。然而,std::abs过载,可以同时处理这两个问题。@Coatless谢谢您的评论。老实说,我不确定关于呼叫解决方案的具体情况。这取决于Rcpp公开的名称以及名称空间;例如,它是否包括Mth.H/CMAth/NONE、STDLIB H/CSSTDLB/2,不可能是C++版本和编译器所使用的,RCPP是否定义了自己的包装器/垫片、隐式声明等等。这就是为什么我喜欢用它们的命名空间来限定资格函数调用的原因;你通常不必担心这些复杂的细节。但在这种情况下你可能是对的。
  n = length(dat)
  s_lower = 0
  s_square_lower = 0
  s_upper = 0
  s_square_upper = 0
  for (i in 1:(kn-1)) {
    s_lower = s_lower + dat[i]
    s_square_lower = s_square_lower + dat[i] * dat[i]
  }
  for (i in kn:n) {
    s_upper = s_upper + dat[i]
    s_square_upper = s_square_upper + dat[i] * dat[i]
  }
  M = 0

  for (k in kn:(n-kn)) {
    s_lower = s_lower + dat[k]
    s_square_lower = s_square_lower + dat[k] * dat[k]
    s_upper = s_upper - dat[k]
    s_square_upper = s_square_upper - dat[k] * dat[k]

    sdk = sqrt((s_square_lower - (s_lower)^2/k +
                         s_square_upper -
                         (s_upper)^2/(n-k))/n)
    M_candidate = sqrt(kn) * abs(s_lower / k - s_upper / (n - k)) / sdk

    cat('k', k, '\n',
        "s_lower", s_lower, '\n',
        's_square_lower', s_square_lower, '\n',
        's_upper', s_upper, '\n',
        's_square_upper', s_square_upper, '\n',
        'sdk', sdk, '\n',
        'M_candidate', M_candidate, '\n\n')

    if (M_candidate > M) {
      M = M_candidate
    }
  }
cppFunction('double statZn_cpp(NumericVector dat, double kn) {
  int n = dat.size();
  double s_upper = 0, s_square_upper = 0; // Get total sum and sum of squares; this will be the "upper sum" (i.e. the sum above k)
  double s_lower = 0, s_square_lower = 0; // The "lower sums" (i.e. those below k)
  for (int i = 0; i < kn - 1; ++i) { s_lower += dat[i]; s_square_lower += dat[i] * dat[i]; } // Get lower sums; Go to kn - 1 to prevent double-counting in main
  for (int i = kn - 1; i < n; ++i) { s_upper += dat[i]; s_square_upper += dat[i] * dat[i]; } // Get upper sum
  double M = 0; // The maximum, which will be returned
  double M_candidate; // A candidate for the new maximum, used in a loop
  // Compute the test statistic
  for (int k = kn; k <= (n - kn); ++k) {
    // Update s and s_square for both lower and upper
    s_lower += dat[k-1];
    s_square_lower += dat[k-1] * dat[k-1];
    s_upper -= dat[k-1];
    s_square_upper -= dat[k-1] * dat[k-1];
    // Get estimate of sd for this k
    double sdk = std::sqrt((s_square_lower - s_lower*s_lower / k + s_square_upper - s_upper*s_upper / (n - k))/n);
    M_candidate = std::abs(s_lower / k - s_upper / (n - k)) / sdk;
    if (M_candidate > M) M = M_candidate; // Choose new maximum
  }
  return std::sqrt(kn) * M;
}');

statZn_cpp(1:20,4); ## you will get 6.963106, which is the correct answer
## [1] 6.963106
statZn_cpp(1:20*10,4); ## Scaling should not matter; will also yield the correct answer of 6.963106
## [1] 6.963106
statZn_cpp(1:20/10,4); ## yields the wrong answer of 6.575959
## [1] 6.963106
statZn_cpp(1:20/100,4); ## again gives you the obviously wrong answer of 0.
## [1] 6.963106
set.seed(1L); statZn_cpp(rnorm(20),4); ## More to the point (and relevant to my research, which involves simulation studies), the answer is almost always 0, which is wrong.
## [1] 1.270117