【问题标题】:Divide by 3, function in C#除以 3,C# 中的函数
【发布时间】:2012-03-09 06:41:28
【问题描述】:

我有一个函数返回我的 int 值列表取决于值的一部分:

private List<int> GetColumn(int total, int column)
{
    List<int> retList = new List<int>();

    if (total <= 0)
    {
        return retList;
    }

    if (column < 0 || column > 2)
    {
        column = 0;
    }

    int pageSize = total / 3;

    int startIndex = column * pageSize;
    int endIndex = column * pageSize + pageSize;

    if (endIndex > total)
    {
        endIndex = total;
    }

    for (int i = startIndex; i < endIndex; i++)
    {
        retList.Add(i);
    }

    return retList;

}

但它工作错了,因为: 获取列(17, 0)

它返回 [0,1,2,3,4],但应该返回 [0,1,2,3,4,5]
对于 GetColumn(17, 1) - [6,7,8,9,10,11]
对于 GetColumn(17, 2) - [12,13,14,15,16]

对于 16,它应该返回: 对于 GetColumn(16, 0) - [0,1,2,3,4,5]
对于 GetColumn(16, 1) - [6,7,8,9,10]
对于 GetColumn(16, 2) - [11,12,13,14,15]

我应该对我的功能进行哪些更改?谢谢!

【问题讨论】:

  • 您的第一个示例为 (17,1) 调用返回 6 个元素,但为 (17,0) 和 (17,2) 调用返回 5 个元素。如果元素的数量不能被三整除,这个逻辑将如何工作?一个随机的“页面”应该得到额外的元素,还是总是在中间?如果有两个“额外”元素呢?中间第一个,还是中间最后一个?
  • int 除以int 仍然是int。至少有一个操作数必须是float/double 才能使结果非int
  • 不,分3个以上没有必要

标签: c# asp.net divide


【解决方案1】:

如果这是您需要的(数字按列增加,但需要先填充行):

for 16:
0  6  11
1  7  12
2  8  13
3  9  14
4  10 15
5

for 17:
0  6  12
1  7  13
2  8  14
3  9  15
4  10 16
5  11

您需要定义哪一列得到余数:

int remainder = total % 3;

如果余数为 1,则只有第一列是 6 个元素。如果余数为 2,则第一列和第二列是 6 个元素。你需要根据这个计算startIndex和endIndex。

所以;

int pageSize = total / 3;
int remainder = total % 3;

int startIndex = column * pageSize + min(column, remainder);
int endIndex = startIndex + pageSize + (remainder > column ? 1 : 0);

应该可以。我刚刚对其进行了测试,它适用于与 3 不同的行大小。

这是我获得公式的方式,绘制表格是整理此类算法的好习惯:

r:Remainder, c:column, ps:pagesize(如上计算)

StartingIndex:
.  |r:0 |r:1   |r:2
----------------------
c:0|0   |0     |0
----------------------
c:1|ps  |ps+1  |ps+1
----------------------
c:2|ps*2|ps*2+1|ps*2+2

如果将表格扩展为行大小 4,您可以看到一个模式:

StartingIndex:
.  |r:0 |r:1   |r:2   |r:3
------------------------------
c:0|0   |0     |0     |0
------------------------------
c:1|ps  |ps+1  |ps+1  |ps+1
------------------------------
c:2|ps*2|ps*2+1|ps*2+2|ps*2+2
------------------------------
c:3|ps*3|ps*3+1|ps*3+2|ps*3+3

您要添加的值是相关列和余数的最小值

与 endIndex 类似,当您为给定的余数与列构建表时,可以看到所需的列长度。我暂时不会写这个,因为在这里绘制表格花费了太多时间,我相信你已经明白了。

【讨论】:

  • 是的,这正是我所需要的,但是如何在函数中实现以返回第 1 列和第 2 列的正确范围?
  • 谢谢,但是 startIndex 和 endIndex 对于不同的列是错误的 :(
  • 哎呀!我在 endIndex 计算中写错了“余数 > 列”。它现在应该可以正常工作了,我测试了它。
【解决方案2】:

整数除法向零舍入。所以 17/3 = 5 和 -17/3 = -5
我想你想要的是像这样四舍五入到下一个整数

int pageSize = (int)Math.Ceiling(total / 3d);

【讨论】:

  • 在这种情况下它也不起作用,因为对于 GetColumn(16, 0) 它返回 5 个值,但应该返回 6, GetColumn(16, 1) - 5, GetColumn(16, 2 ) - 5
  • 它也不能正常工作,因为对于第一和第二列它返回 6 个值,但对于第三列只有 4,但应该返回:6、5、5
【解决方案3】:

如果我理解正确,要求是:

If the number is 3n,   divide it in 3 groups of n,   n   and n   elements.
If the number is 3n+1, divide it in 3 groups of n+1, n   and n   elements.
If the number is 3n+2, divide it in 3 groups of n+1, n+1 and n   elements.

最好的办法是在代码中明确说明,并避免任何“聪明”的逻辑。 直接的拆分归结为:

If the number is 3n, the divisions are:
     0 ..  n-1
     n .. 2n-1
    2n .. 3n-1
If the number is 3n+1, the divisions are:
     0 .. n
   n+1 .. 2n
  2n+1 .. 3n
If the number is 3n+2, the divisions are:
     0 .. n
   n+1 .. 2n+1
  2n+2 .. 3n+1

在 c# 中会是这样的:

public static List<int> Divide3Columns(int total, int column)
{
  int startIndex = 0;
  int endIndex = 0;
  int pageSize = total / 3;

  if (total % 3 == 0)
  {
    startIndex = column * pageSize;
    endIndex = (column + 1) * pageSize - 1;
  }

  if (total % 3 == 1)
  {
    if (column == 0)
    {
      startIndex = 0;
      endIndex = pageSize; //pageSize + 1 elements;
    }
    else
    {
      startIndex = column * pageSize + 1;
      endIndex = (column + 1) * pageSize;
    }
  }

  if (total % 3 == 2)
  {
    if (column == 2)
    {
      startIndex = 2 * pageSize + 2;
      endIndex = 3 * pageSize + 1; //same as total - 1;
    }
    else
    {
      startIndex = column * (pageSize + 1);
      endIndex = (column + 1) * pageSize + column;
    }
  }

  List<int> result = new List<int>();
  for (int i = startIndex; i <= endIndex; i++)
  {
    result.Add(i);
  }
  return result;
}

答案假定我们将始终divide in 3, and only 3 columns。如果数字是可变的,那么确定列的逻辑可以概括。

【讨论】:

  • @ihorko 修复了它,并添加了一个更完整的示例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-02
  • 2021-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多