公式为正整数产生1,否则产生0

时间:2014-12-18 20:48:09

标签: c# function math

我有一个函数(f)获取多个项目(n)和多个列(c)并返回最佳布局作为每列的项目数组。我将最佳定义为尽可能正方形。因此f(4,4)将返回[4,4,4,4],f(17,4)将返回[5,4,4,4],而f(1,4)将返回[1,0,4] ,0,0]。我的功能在我的所有测试中都能正常工作,但我希望改变它。我这样做的愿望不是因为我期待提高性能。我只想这样做,因为我正在尝试并希望学习不同的技术。

以下是代码:

    public static int[] f(int n, int c){
        int[] a = new int[c];
        if(c>0 && n>=0){
            int opt = (n-(n%c))/c;
            n = n - (opt*c);
            for(int i = 0;i<a.Length;i++){
                a[i] = opt;
                if(n>0){
                    a[i]++;
                    n--;
                }
            }
        }
        return a;
    }

该功能首先确定每个col的最佳项目数:

int opt = (n-(n%c))/c;

因此f(17,4)将产生4,f(19,4)也将产生4,而f(3,4)将产生0.然后计算提醒:

n = n - (opt*c);
然后我循环遍历数组(长度为c)并指定[i]等于最佳值。最后,如果提醒大于0,我将1添加到[i]。这同样在整个阵列中分发提醒。这是我想改变的部分。

而不是检查是否(n> 0)并向数组添加1是否存在我可以使用的公式:

a[i] = opt + n*?????;

所以n * ???如果n大于0,则总是等于1;如果n是0或更小,则总是等于0

4 个答案:

答案 0 :(得分:3)

您的问题的简单答案是使用带条件运算符的表达式:

a[i] = opt + (n > 0 ? 1 : 0);
如果(n > 0 ? 1 : 0)大于1,则{p> n0,否则为0

<小时/> 在这方面,有一种更清晰,更简洁的方法来实现您的算法。

  1. 确定可以在插槽之间均匀分配的项目总数(调用此average)。它的值为n / c(使用整数除法)。
  2. 确定均匀分布后剩余的余数(调用此remainder)。其值为n % c
  3. 将值average + 1放在第一个remainder位置,然后将average放在其余位置。
  4. 这方面的实施将是:

    public static int[] Distribute(int total, int buckets)
    {
        if (total < 0) { throw new ArgumentException("cannot be less than 0", "total"); }
        if (buckets < 1) { throw new ArgumentException("cannot be less than 1", "buckets"); }
    
        var average = total / buckets;
        var remainder = total % buckets;
    
        var array = new int[buckets];
    
        for (var i = 0; i < buckets; i++)
        {
            array[i] = average + (i < remainder ? 1 : 0);
        }
    
        return array;
    }
    

    强制性的Linq版本:

    public static int[] DistributeLinq(int total, int buckets)
    {
        if (total < 0) { throw new ArgumentException("cannot be less than 0", "total"); }
        if (buckets < 1) { throw new ArgumentException("cannot be less than 1", "buckets"); }
    
        var average = total / buckets;
        var remainder = total % buckets;
    
        return Enumerable.Range(1, buckets)
                         .Select(v => average + (v <= remainder ? 1 : 0))
                         .ToArray();
    }
    

答案 1 :(得分:2)

int表达式上输出bool的简单函数怎么样?

int IsPositive(int number)
{
    //if number is > 0 return integer one (1), else return integer zero (0)
    return number > 0 ? 1 : 0;
}

然后您可以在代码中使用它:

a[i] = opt + IsPositive(n);
//opt + 1 if n > 0, opt + 0 if n <= 0

更新:根据您的评论,您可以直接移动评估:

a[i] = opt + (n > 0 ? 1 : 0);

顺便说一句:你应该@BradleyDotNET's comment提出一个编程格言。

答案 2 :(得分:1)

如果您想使用公式:

Math.Max(n - Math.Abs(n - 1), 0)

应该做的伎俩。 您的代码应如下所示:

a[i] = opt + Math.Max(n - Math.Abs(n - 1), 0)

答案 3 :(得分:1)

公式的另一个选择是

Math.Max(Math.Sign(n), 0)

如果您正在寻找一个数学公式,我不确定您是否会找到它,因为该函数在n = 0时是不连续的。