How to round floats to integers while preserving their sum?具有以僞代碼寫入的下面的answer,該向量將向量舍入爲整數值,以使元素總和保持不變並且舍入誤差最小化。我想在R.有效地實現這一點(即矢量如果可能)將數值向量的整數向量保留爲整數
例如,舍入這些號碼產生不同的總:
set.seed(1)
(v <- 10 * runif(4))
# [1] 2.655087 3.721239 5.728534 9.082078
(v <- c(v, 25 - sum(v)))
# [1] 2.655087 3.721239 5.728534 9.082078 3.813063
sum(v)
# [1] 25
sum(round(v))
# [1] 26
複製的僞代碼從answer參考
// Temp array with same length as fn.
tempArr = Array(fn.length)
// Calculate the expected sum.
arraySum = sum(fn)
lowerSum = 0
-- Populate temp array.
for i = 1 to fn.lengthf
tempArr[i] = { result: floor(fn[i]), // Lower bound
difference: fn[i] - floor(fn[i]), // Roundoff error
index: i } // Original index
// Calculate the lower sum
lowerSum = lowerSum + tempArr[i] + lowerBound
end for
// Sort the temp array on the roundoff error
sort(tempArr, "difference")
// Now arraySum - lowerSum gives us the difference between sums of these
// arrays. tempArr is ordered in such a way that the numbers closest to the
// next one are at the top.
difference = arraySum - lowerSum
// Add 1 to those most likely to round up to the next number so that
// the difference is nullified.
for i = (tempArr.length - difference + 1) to tempArr.length
tempArr.result = tempArr.result + 1
end for
// Optionally sort the array based on the original index.
array(sort, "index")
儘管此解決方案比我的解決方案更快,並且保留了所需的總和,但不幸的是,它不會最小化問題中所要求的舍入誤差。例如,與'v < - C(2.655087,3.721239,5.728534,9.082078,3.813063)','的所述smart.round'舍入誤差,'總和(ABS(smart.round(ⅴ)-v))',返回1.474329,而'diffRound','sum(abs(diffRound(v)-v))'的舍入誤差返回1.606633。 – josliber
這是事實,總體舍入誤差不會被diff方法最小化。我不確定這是否是該問題的強烈要求。 – Bulat
原始問題有這個條款:「考慮到滿足這四個條件,使舍入方差(sum((in [i] - fn [i])^ 2))最小化的算法是可取的,但這不是一個大問題「。 – Bulat