2015-01-21 37 views
0

有一种简单的,有效的和正确的(即不涉及转换到/从双)的方式做地板整数除法(像例如Python offers)在C#。地板整数除法

换句话说,以下的高效版本,不会遭受长/双转换损失。

(long)(Math.Floor((double) a/b)) 

或者是否必须自己实施它,例如,

static long FlooredIntDiv(long a, long b) 
{ 
    if (a < 0) 
    { 
     if (b > 0) 
      return (a - b + 1)/b; 
     // if (a == long.MinValue && b == -1) // see *) below 
     // throw new OverflowException(); 
    } 
    else if (a > 0) 
    { 
     if (b < 0) 
      return (a - b - 1)/b; 
    } 
    return a/b; 
} 

*)虽然除法运算符 OverflowException leaves it open是否里面 unchecked提出,在现实中它确实在我的系统上掷()和 Visual Studio .NET 2003 version的C#4规范甚至规定扔:

如果左操作数是最小的可表示的int或long值并且右操作数是-1,则无论操作是在检查的还是在未检查的上下文中发生,[..] System.OverflowException总是在此情况下抛出。

编辑

checkedunchecked的划掉报表都不错,很好,但checked实际上只是一个compile time concept,所以不管我的功能应环绕不管调用函数的代码是否在checked之内,或者无论如何抛出都取决于我。

+1

你的意思是,将结果传递给'Math.Floor'的替代方法? – 2015-01-21 04:38:03

+0

整数除法已经在做这个,不是直接调用'Math.Floor',而是结果是一样的,它切断了整个小数部分。在这种情况下'Math.Floor'是多余的。 – 2015-01-21 04:39:37

+1

@maremp:只有积极的结果。有关与C#'/'运算符实现不同的“底层”否定结果的示例,请参阅OP的表。 – 2015-01-21 04:40:25

回答

0

它以任何健全的编程语言(遵循我们正常的操作顺序)运作的方式是-1.0/3.0等于-(1.0/3.0),即-0.3333...。所以如果你想把它转换成一个int,那么你真的需要考虑演员/演员,而不是分部。因此,如果您想要这种行为,您必须使用(int)Math.Floor(a/b)或自定义代码。

+0

谢谢,我删除了我的答案的那一部分。我在计算物理学中学到的一些概念已经因滥用而被破坏,并且以无意义的方式重组。 :) 关于哪些操作部分应该投入规则/指导原则,目标是由于浮点不精确而丢失最少的信息,但自从大学以来我没有真正使用这些操作,因此忘记了具体细节。 – piojo 2015-01-22 20:06:33

1

你可以试试这个:

if (((a < 0)^(b < 0)) && (a % b != 0)) 
{ 
    return (a/b - 1); 
} 
else 
{ 
    return (a/b); 
} 

编辑(在下面的评论一些讨论后):

不使用的if-else,我会是这样的:

return (a/b - Convert.ToInt32(((a < 0)^(b < 0)) && (a % b != 0))); 

备注:Convert.ToIn32(bool value)也需要跳转,详见implemention的方法:

return value? Boolean.True: Boolean.False; 

从理论上讲,这是不可能计算师为a = long.MinValueb = -1L,由于预期的结果是a/b = abs(long.MinValue) = long.MaxValue + 1 > long.MaxValue。 (长范围是–9,223,372,036,854,775,8089,223,372,036,854,775,807。)

+0

PS:^是异或运算符 – Bhaskar 2015-01-21 05:09:13

+0

谢谢L16H7。在实现上面的FlooredIntDiv时,我开始类似于你的解决方案,这种解决方案效率很高,我相信和我一样正确(我没有想过你的解决方案是否抓住所有'0'角落的情况),但我去了'if/else'路线,因为我认为它更容易阅读。所以它相当于我的示例实现,但既不容易,也不是更有效。 – 2015-01-21 05:16:42

+0

通常,“高效”公式不应使用任何“if”语句等。它应该纯粹基于低级算术运算符。 – 2015-01-21 05:36:04