Rcpp-如何计算行和正好为1的矩阵
我试图创建一个带有随机数的矩阵,其中Rcpp-如何计算行和正好为1的矩阵,r,floating-point,precision,rcpp,R,Floating Point,Precision,Rcpp,我试图创建一个带有随机数的矩阵,其中行和应该正好为1 我已经有了一个条件,可以检查行和是否不是1,并尝试更正它 当我打印出结果时,它看起来是正确的,但如果我测试所有值是否为1,它会给我一些错误的值 我该怎么纠正呢 library(Rcpp) cppFunction(' NumericMatrix imembrandc(int n, int k) { NumericMatrix u( n , k ); IntegerVector sequ = seq(1,100); NumericV
行和
应该正好为1
我已经有了一个条件,可以检查行和
是否不是1,并尝试更正它
当我打印出结果时,它看起来是正确的,但如果我测试所有值是否为1,它会给我一些错误的值
我该怎么纠正呢
library(Rcpp)
cppFunction('
NumericMatrix imembrandc(int n, int k) {
NumericMatrix u( n , k );
IntegerVector sequ = seq(1,100);
NumericVector sampled;
for (int i=0; i < k; ++i) {
sampled = sample(sequ, n);
u(_,i) = sampled / sum(sampled);
}
if (is_true(any(rowSums(u) != 1))) {
u(_,1) = u(_,1) + (1 - rowSums(u));
}
return(u);
}')
[1] 11
但检查它会发现一些错误:
rowSums(res) == 1
[1] 真的真的假真的假真
生成总和为1的n
随机数的方法是从[0,1)
生成n-1
值,将0和1添加到列表中,并取排序列表的差值。当然,这取决于随机数的分布。这可以用R表示为
set.seed(42)
v[1]0.28613953 0.35560598 0.18870211 0.08435842 0.02226937 0.06292459
总数(五)
#> [1] 1
由(v0.2.1)于2019-05-24创建
以C++为例:
#包括
使用名称空间Rcpp;
//[[Rcpp::导出]]
数字矩阵imembrandc(整数n,整数k){
数值矩阵u(n,k);
对于(int i=0;i
请注意,我首先生成行,而您正在生成列,然后尝试更正rowSum
。输出:
> set.seed(42)
> res = imembrandc(n = 10, k = 5)
> rowSums(res)
[1] 1 1 1 1 1 1 1 1 1 1
> rowSums(res) == 1
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
> all.equal(rowSums(res),rep(1, nrow(res)))
[1] TRUE
顺便说一句,
all.equal
也为您的矩阵提供了TRUE
,因为差异非常小。但是我发现最好从一开始就避免这个问题。如果您使用View(res)
你会发现它们不是真正的1res
是一个值矩阵,值不应该是1。但是每行的总和应该是。因此如果你查看(行总和(res))你也会看到1,但实际上不是。我的问题是,我如何确保行和确实是1。在浮点运算中,哪里有证据证明结果数字的和正好是1?至少对我来说all(行和(res)==1)
givingTRUE
足以证明:)此方法产生的分布将向低数字倾斜,导致少数样本中存在不同数量的增加,这将成为舍入误差的肥沃土壤。因此,经验可能会给人一种误导的印象。问题要求采用一种方法,其中sa我是1。提供一个反证。考虑两个有效数字的十进制浮点。递增数的序列可能是0,005,11, 1。实数的差值是。005,105,和89.三个数字。105必须被舍入到两个数字,和偶数规则的最接近的关系给出。10。所以G。生成的数字是.005、.10和.89。加上前两个产生.10(实数和.105,四舍五入到.10),第三个产生.99。正如我在对答案的评论中所指出的,这种情况非常罕见。
> set.seed(42)
> res = imembrandc(n = 10, k = 5)
> rowSums(res)
[1] 1 1 1 1 1 1 1 1 1 1
> rowSums(res) == 1
[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
> all.equal(rowSums(res),rep(1, nrow(res)))
[1] TRUE