# 关于x86下VB、C#、VC中的整数运算需要注意的地方

using System;

namespace IntegerArithmetic
{
class Program
{
static void Main(string[] args)
{
Int32 a = (-1) / 8;                   //0
Int32 b = (-1) % 8;                   //-1
Int32 c = 1 << 32;                    //1
UInt32 d = 1U << 32;                  //1

Int32 e = (-1) / (-8);                //0
Int32 f = (-1) % (-8);                //-1
Int32 g = (-1) << 32;                 //-1
Int32 h;                              //-1
Int32 i = Math.DivRem(-1, 8, out h);  //0

Console.WriteLine(String.Format("a = {0}", a));
Console.WriteLine(String.Format("b = {0}", b));
Console.WriteLine(String.Format("c = {0}", c));
Console.WriteLine(String.Format("d = {0}", d));
Console.WriteLine(String.Format("e = {0}", e));
Console.WriteLine(String.Format("f = {0}", f));
Console.WriteLine(String.Format("g = {0}", g));
Console.WriteLine(String.Format("h = {0}", h));
Console.WriteLine(String.Format("i = {0}", i));
}
}
}


1.整数除法和模运算

x DIV y = TruncToZero(x / y)
x MOD y = x - (x DIV y) * y


MOD表示模运算(VB中为Mod, C#和C++中为%)；
DIV表示整数除法(VB中为\，C#和C++中为/)；
TruncToZero(r)是指取一个符号与r相同，且绝对值不大于|r|的绝对值最大的整数；
TruncToZero(r) = sign(r) * max{|x|: |x| <= |r|}
/表示实数除法。

bool is_odd(int n) {
return n % 2 == 1;
}


floored division：模得的值的符号与模数一致

x DIV y = floor(x / y)
x MOD y = x - (x DIV y) * y


Euclidean definition: 模得的值始终为正

x DIV y = if y > 0
floor(x / y)
else
ceil(x / y)
x MOD y = x - (x DIV y) * y



/// <summary>modulo from Knuth's floored division</summary>
public static Int32 Mod(this Int32 a, Int32 m) {
Int32 s = Math.Sign(m);
Int32 pm = Math.Abs(m);
return s * (((s * a) % pm) + pm) % pm;
}

/// <summary>Knuth's floored division</summary>
public static Int32 Div(this Int32 a, Int32 b)
{
return (a - a.Mod(b)) / b;
}



public static Int32 Mod(this Int32 a, Int32 m)
{
Int32 r = a % m;
if (((r < 0) && (m > 0)) || ((r > 0) && (m < 0))) { r += m; }
return r;
}

public static Int32 Div(this Int32 a, Int32 b)
{
if (b == 0) { throw new DivideByZeroException(); }
Int32 r = a.Mod(b);
if ((a > 0) && (r < 0))
{
if (a - Int32.MaxValue > r) { return (a - Math.Abs(b) - r) / b + Math.Sign(b); }
}
else if ((a < 0) && (r > 0))
{
if (a - Int32.MinValue < r) { return (a + Math.Abs(b) - r) / b - Math.Sign(b); }
}
return (a - r) / b;
}


2.移位运算

Int32 x, Int32 y
x << y = x SAL (y MOD 32)
x >> y = x SAR (y MOD 32)
UInt32 x, Int32 y
x << y = x SHL (y MOD 32)
x >> y = x SHR (y MOD 32)


y MOD 32 = y AND 0x1F

public static UInt32 SHL(this UInt32 a, Int32 n)
{
if (n >= 32) { return 0; }
if (n < 0) { return a.SHR(-n); }
return a << n;
}

public static UInt32 SHR(this UInt32 a, Int32 n)
{
if (n >= 32) { return 0; }
if (n < 0) { return a.SHL(-n); }
return a >> n;
}

public static Int32 SAL(this Int32 a, Int32 n)
{
if (n >= 32) { return 0; }
if (n < 0) { return a.SAR(-n); }
return a << n;
}

public static Int32 SAR(this Int32 a, Int32 n)
{
if (n >= 32)
{
if (Convert.ToBoolean(a & Int32.MinValue))
{
return -1;
}
else
{
return 0;
}
}
if (n < 0) { return a.SAL(-n); }
return a >> n;
}


3.修正的使用时机

1)整数除法和模运算修正的使用时机是：

(n - 1) MOD m


(n + m -1) MOD m


2)移位运算修正的使用时机

Int32 Mask = 1 << n - 1


Int32 Mask = 1.SAL(n) - 1


4.结论

x86下的整数运算远比人们所想象的复杂。

[1] http://en.wikipedia.org/wiki/Modulo_operation

posted @ 2010-09-30 15:34 地狱门神 阅读(...) 评论(...) 编辑 收藏