地板整数除法 [英] Floored integer division

查看:125
本文介绍了地板整数除法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有一种简单,有效和正确的方式(即不涉及到双精度的转换)来进行泛整数除法(例如

Is there an easy, efficient and correct (i.e. not involving conversions to/from double) way to do floored integer division (like e.g. Python offers) in C#.

换句话说,下面的有效版本不会带来长期/双重转换损失.

In other words, an efficient version of the following, that does not suffer from long/double conversion losses.

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

还是必须自己实现,例如

or does one have to implement it oneself, like e.g.

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;
}

<罢工> *)尽管Division运算符的C#4规范将其打开是否将OverflowException放在unchecked内,但在确实会(在我的系统上)和 Visual Studio .NET 2003版本

*) Although the C# 4 spec of the Division operator leaves it open whether OverflowException is raised inside unchecked, in reality it does throw (on my system) and the Visual Studio .NET 2003 version even mandated it throw:

如果左操作数是可表示的最小int或long值,而右操作数是–1,则在这种情况下始终抛出[..] System.OverflowException,无论该操作是在选中还是未选中的上下文中发生.

If the left operand is the smallest representable int or long value and the right operand is –1, [..] System.OverflowException is always thrown in this situation, regardless of whether the operation occurs in a checked or an unchecked context.

修改

关于checkedunchecked的划掉的语句都很好,但是 checked实际上只是一个

The crossed out statements about checked and unchecked are all nice and well, but checked is in fact only a compile time concept, so whether my function should wrap around or throw is up to me anyway, regardless of whether code calling the function is inside checked or not.

推荐答案

您可以尝试以下操作:

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

编辑(在下面的评论中进行了一些讨论之后):

Edit (after some discussions in comments below):

如果不使用if-else,我会这样:

Without using if-else, I would go like this:

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

注意:Convert.ToIn32(bool value)也需要跳转,请参见实现方法的a>:

Note: Convert.ToIn32(bool value) also needs a jump, see implemention of the method:

return value? Boolean.True: Boolean.False;

理论上,由于预期结果为a/b = abs(long.MinValue) = long.MaxValue + 1 > long.MaxValue,因此无法计算a = long.MinValueb = -1L的除法. (长范围是–9,223,372,036,854,775,8089,223,372,036,854,775,807.)

Theoretically, it is not possible to calculate the division for a = long.MinValue and b = -1L, since the expected result is a/b = abs(long.MinValue) = long.MaxValue + 1 > long.MaxValue. (Range of long is –9,223,372,036,854,775,808 to 9,223,372,036,854,775,807.)

这篇关于地板整数除法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆