【问题标题】:Comparing floats with more than 1 integer将浮点数与超过 1 个整数进行比较
【发布时间】:2017-02-13 15:02:45
【问题描述】:

我想测试一个矩阵的行总和是 0 还是 1。总和是浮点数,所以直接与 == 比较是行不通的。

这是一个例子:

# Sample matrix
mat <- matrix(rnorm(50), nrow = 5)

# Choose some row to sum to 1.  I will not know in advance which rows these are
sum.to.1 <- sample(1:5, 3)

mat.normalized <- mat

# Some rows sum to 1
mat.normalized[sum.to.1, ] <- mat[sum.to.1, ] / rowSums(mat[sum.to.1, ])

# Remaining rows sum to 0
mat.normalized[-sum.to.1, ] <- mat[-sum.to.1, ] - rowMeans(mat[-sum.to.1, ])

rowSums(mat.normalized)  # very close, but not exactly, 1 or 0

# I want something like this:
# all(rowSums(mat.normalized) %in% c(0, 1))

如果我只是测试行总和是否为 1,或者如果我提前知道哪些行将为 0,我会使用all.equal。但有些行的总和为 0,我不知道 先验 会是哪些行。

我也不能使用round(我认为),因为无论它们有多接近,所有行都会四舍五入为 1 或 0。

有什么想法吗?似乎应该有一些简单的东西,但我想不通。

【问题讨论】:

  • 您可以测试与0/1的绝对差是否小于阈值
  • round(rowSums(mat.normalized), floor(-log10(.Machine$double.eps)))

标签: r floating-point


【解决方案1】:

可能有一个更有说服力的答案,但您可以像这样使用sapplyall.equal 的2 次传递。

# get the sums
mySums <- rowSums(mat.normalized)

# run through values twice. Check for equal to 1, equal to 0, then sum the results
all(sapply(mySums, function(i) isTRUE(all.equal(i, 1))) +
    sapply(mySums, function(i) isTRUE(all.equal(i, 0))) == 1)
[1] TRUE

我添加了== 1,因为+ 将返回一个数字向量,而all 抱怨这一点。正如@cath 的评论所暗示的,最后可以避免== 1。一种这样的尝试是使用Reduce

all(Reduce("|", sapply(mySums, function(i) isTRUE(all.equal(i, 1))),
                sapply(mySums, function(i) isTRUE(all.equal(i, 0)))))

mapply

all(mapply("|", sapply(mySums, function(i) isTRUE(all.equal(i, 1))),
           sapply(mySums, function(i) isTRUE(all.equal(i, 0)))))

【讨论】:

  • 好点,我将添加第二个选项。我将sapply 输出相加,得到一个数字向量。 all 将在数字向量上工作,但会发出警告并抱怨它。例如,试试all(1)
  • 我在上面的 cmets 中接受了@Roland 的回答,但这同样好,谢谢。
猜你喜欢
  • 2013-11-19
  • 2022-01-09
  • 2021-05-28
  • 2017-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多