如何舍入 Excel 中的小数列表,使整数之和等于定义的总数?

How to round a list of decimals in Excel, so that the sum of the whole numbers equal a defined total?

难以开发 excel 将小数列表四舍五入的函数,以便所有数字的总和等于原始数字或定义的总数。

编辑 我想这样做的一种方法是编写一个函数,首先搜索最大的数字并将它们四舍五入到最接近的整数。然后计算这个整数,函数继续下一个,直到总数等于目标总数。

我 运行 遇到的问题是,如果有太多接近 0 的数字,那么该函数将永远不会等于目标总数。所以该函数需要做的是识别最大的小数,将它们四舍五入,计数,然后继续下一个,直到计数的总和等于目标总数。剩下的数据可以舍入为 0。

抱歉,我希望这更清楚....

我正在处理更大的数据集,其中四舍五入整数的总和与原始总和的偏差更大。

如果这可以用 excel 函数来完成,那就更好了,否则我也愿意在 VBA 中做。

谢谢!

编辑 3:这是一个示例数据集:

我同意@pghcpa 的观点,这是一道算术题。 一种解决方案:

  1. 按小数部分降序排列数字
  2. 每个人都发言(即忽略分数)
  3. 取这些楼层的总和
  4. 将该总和与所需总和进行比较,取差 这样你 可能 有一个正的差异,所以你可以从顶部开始,向下每个数字加 1,直到差异消失。

请研究我的项目VBA.Round

浏览到段落 Rounding a series of numbers to a sum

这里的代码太多 post,但是包含一个示例工作簿供下载。

示例:

此函数将读取分布值的范围,对总和进行四舍五入,并用四舍五入的值 2 和零小数填充两个范围,总计为请求的总数(已通过公式确认):

' Practical example for using Excel ranges for RoundSum
'
' Source URL:
'   
'
' 2020-09-14. Gustav Brock, Cactus Data ApS, CPH.
'
Public Sub RoundDistribution()

    ' Named ranges. These should pairwise match in row size.
    Const VolumeName        As String = "Volume"
    Const PercentValuesName As String = "Percent_Distribution"
    Const ValuesName        As String = "Distribution"
    Const RoundedValuesName As String = "Rounded_Distribution"
    
    Dim Range       As Excel.Range
    
    Dim Values()    As Currency
    Dim Results()   As Currency
    
    Dim Total       As Integer
    Dim Index       As Integer
    
    ' Read percent distribution values from the named range.
    Set Range = ThisWorkbook.Names(PercentValuesName).RefersToRange
    ' Read original volume value.
    Total = ThisWorkbook.Names(VolumeName).RefersToRange(1, 1)
    
    ' Dim input and output arrays.
    ReDim Values(1 To Range.Rows.Count)
    ReDim Results(1 To Range.Rows.Count)
    
    ' Fill input array.
    For Index = LBound(Values) To UBound(Values)
        Values(Index) = Range(Index, 1)
    Next
    
    ' Round total and retrieve array with distribution values.
    Results = RoundSum(Values, RoundMid(Total), 2)
    
    ' Fill named range with distribution values.
    For Index = LBound(Results) To UBound(Results)
        ThisWorkbook.Names(ValuesName).RefersToRange(Index, 1) = Results(Index)
    Next
    
    ' Round total and retrieve array with rounded distribution values.
    Results = RoundSum(Values, RoundMid(Total))
    
    ' Fill named range with rounded distribution values.
    For Index = LBound(Results) To UBound(Results)
        ThisWorkbook.Names(RoundedValuesName).RefersToRange(Index, 1) = Results(Index)
    Next
    
End Sub

输出:

请注意,该函数能够四舍五入到任意小数位数,并且 select 值 0.34 的一个实例以获得匹配。

完整的演示(Excel 工作簿)和代码仍在 GitHub上下载。