数学舍入问题合计>;100%
本文关键字:gt 100% 舍入 问题 | 更新日期: 2023-09-27 18:23:52
我有三个值,它们都被四舍五入到没有小数点的位置(即5%、25%、70%),除了我的70%实际上是70.6%,所以它变成了71%,这使得我的总数为5%、25%和71%=101%,这不好,尤其是因为我有一个条形图,如果它超过100%的宽度,就会变得非常糟糕。
如何确保我的3个值永远不会超过100%?现在我正在使用数学。Round(值,0)有什么开关/选项可以让我的3个值的总和不超过100%吗?
感谢
如果三个值的总和总是必须达到100,则只对其中两个值进行四舍五入,并使用计算第三个值
third = 100 - Math.Round(a) - Math.Round(b);
注意:您的结果也可能太小。如果你有三个值33.333333,四舍五入加起来会得到99!
编辑(回应@BlueRajaDannyPflughoeft的评论)
如果有多个值,则所有舍入误差的总和可能会变大。因此,将其转换为最后一个值不是一个好主意。对于这些情况,我建议连续四舍五入。
double[] values = new double[] { 17.2, 3.7, 4.6, 5.8 };
int[] percent = new int[values.Length];
double sum = values.Sum();
int totalPercent = 100;
for (int i = 0; i < values.Length; i++) {
double rawPercent = sum == 0 ? 0 : values[i] / sum * totalPercent;
sum -= values[i];
int roundedPercent = (int)Math.Round(rawPercent);
totalPercent -= roundedPercent;
percent[i] = roundedPercent;
}
// values = { 17.2, 3.7, 4.6, 5.8 }
//
// Percents:
// percent => { 55, 12, 15, 18 }
// raw (exact) => { 54.952, 11.821, 14.696, 18.530 } (rounded to 3 decimals)
// raw continuous => { 54.952, 11.809, 14.596, 18.000 }
它并不完美,但是误差永远不应该超过1%。下面是的另一个例子
values = { 10.0, 10.0, 10.0, 10.0, 10.0, 10.0 }
Percents:
rounded => { 17, 17, 16, 17, 16, 17 }
raw (exact) => { 16.667, 16.667, 16.667, 16.667, 16.667, 16.667 }
raw continuous => { 16.667, 16.600, 16.500, 16.667, 16.500 17.000 }
不要添加舍入值,希望得到任何有意义的值。将未舍入的值相加。如果这不能达到你想要的效果,你必须解释你认为通过添加四舍五入的值来实现的目标。
如果您不在乎这些值的总和可能小于100,那么简单的解决方案就是始终使用Math.Floor
。
如果你想向上/向下取整,结果正好是100,这会变得更有趣。这里有一种方法–将它们全部向下四舍五入,然后有选择地将它们向上四舍五舍五入——首先是最大分数,直到你再次达到100:
public static void RoundTo100Percent(IList<double> list)
{
// get the sort order before changing any items
IList<int> sortOrder = list.Select((n, i) => new { Key = n - Math.Truncate(n), Index = i }).OrderByDescending(ki => ki.Key).Select(ki => ki.Index).ToList();
// round them all down to start with
for (int i = 0; i < list.Count; i++)
{
list[i] = Math.Floor(list[i]);
}
// then round them up selectively, starting with those with the highest fractional part
// e.g. 5.9 will round up to 6.0 before 7.8 rounds up to 8.0.
int numberOfItemsToRoundUp = 100 - (int)list.Sum();
foreach (int sortIndex in sortOrder.Take(numberOfItemsToRoundUp))
{
list[sortIndex]++;
}
}
你不能像这样在最后做一个检查吗:
if (total > 100)
total = 100;
好吧,如果你不四舍五入,那么它们加起来将达到100%。使用浮点/双精度/小数。问题解决了。
毕竟,你为什么要降低你的准确性--顺便说一句,这就是舍入的作用。
最好对所有账户进行四舍五入,然后将剩余余额作为"统计四舍五进"或类似的余额。
为什么不将所有3个值相加,然后对最终结果进行舍入?33.3+33.3+333.3=99.9,然后四舍五入到100,单独四舍五进只会在99处出现,因为每个都会向下取整。
当我不得不将数据导入到一个系统中时,这个问题就出现了,该系统需要将每个用户的行集的整数百分比添加到一百。
重要的是要认识到,没有"正确"的方法可以做到这一点。例如,给定三个值,每个值都等于1/3,四舍五入的总和等于99,那么应该将哪个值加上1才能使总和为100?没有正确的答案。选一个就行了。
以下是我的PHP解决方案:
function ensureColumnAddsToOneHundred(&$rows, $columnIndex)
{
$percentagesTotalError = getColumnTotal($rows, $columnIndex) - 100;
if ($percentagesTotalError > count($rows))
{
throw new Exception('Percentages total rounding error larger than nValues!');
}
// Add or subtract one from as many rows as is
// necessary to ensure that the total is exactly 100.
for ($i = 0; $i < abs($percentagesTotalError); ++$i)
{
$rows[$i][$columnIndex] += ($percentagesTotalError > 0)? -1: 1;
}
if (getColumnTotal($rows, $columnIndex) != 100)
{
throw new Exception('Percentages total not equal to 100 even after corrections!');
}
}