首页 > 代码库 > 取整函数

取整函数

一、函数说明

double 而言,取整、取余的相关函数和运算符请参考下表:

VB6.0

C 

C# 

Int(x)

floor(x)

Math.Floor(x)

floor表示地板,也就是将技术分享向下取整数,即返回最大的整数技术分享使得技术分享

Math.Floor(1.9)        返回    1

Math.Floor(1.0)        返回    1

Math.Floor(-1.0)        返回    -1

Math.Floor(-1.3)        返回    -2

Math.Floor(-1.9)        返回    -2

 

ceil(x)

Math.Ceiling(x)

ceil表示天花板,也就是将技术分享向上取整数,即返回最小的整数技术分享使得技术分享

Math.Ceiling(1.9)    返回    2

Math.Ceiling(1.3)    返回    2

Math.Ceiling(1.0)    返回    1

Math.Ceiling(-1.0)    返回    -1

Math.Ceiling(-1.9)    返回    -1

Fix(x)

 

Math.Truncate(x)

表示取技术分享的整数部分

Math.Truncate(1.9)    返回    1

Math.Truncate(1.0)    返回    1

Math.Truncate(-1.0)    返回    -1

Math.Truncate(-1.9)    返回    -1

Round(x)

 

Math.Round(x,...)

表示四舍五入,如:四舍五入取整

Math.Round(1.9)        返回    2

Math.Round(1.5)        返回    2

Math.Round(1.3)        返回    1

Math.Round(1.0)        返回    1

Math.Round(-1.0)    返回    -1

Math.Round(-1.3)    返回    -1

Math.Round(-1.5)    返回    -2

Math.Round(-1.9)    返回    -2

x Mod y

fmod(x,y)

x % y

返回 x / y 的余数,其符号与 x 一致。

C语言里 % 只能用于整型变量

注意:VB6.0会对结果四舍五入取整

x / y 

x / y 

x / y 

返回 x / y,对于整数而言,将舍去小数部分。

1、详述Math.Round

Math.Round 还有更丰富的功能

①精确到小数点后n

如:Math.Round(x,n) 表示对 x 只取小数点后 n 位,多余部分四舍五入。

②四舍五入问题

四舍是一定的,但对于五到底入还是不入呢?Math.Round是可以通过MidpointRounding来进行控制的。

MidpointRounding.AwayFromZero 表示五入,这是默认的方法,如:

Math.Round(1.5,MidpointRounding.AwayFromZero);    返回 2

Math.Round(-1.5,MidpointRounding.AwayFromZero);    返回 -2

MidpointRounding.ToEven 就比较有意思了,如果5前面的数字是奇数则入,否则就舍去。如:

Math.Round(2.5,MidpointRounding.ToEven);    返回 2

Math.Round(1.5,MidpointRounding.ToEven);    返回 2

Math.Round(-1.5,MidpointRounding.ToEven);    返回 -2

Math.Round(-2.5,MidpointRounding.ToEven);    返回 -2

二、函数关系

1floorceil的关系

floor(x) = -ceil(-x),同样的ceil(x)=-floor(-x)VB6.0里没有ceil函数,就可以用 -Int(-x) 来代替。

2Math.Truncate floorceil的关系

Math.Truncate(x) = 技术分享

写成C语言代码就是

double Truncate(double x)

{

if(x >= 0.0)

{

return floor(x);

}

return ceil(x); //-floor(-x)

}

三、应用

1、归化角度

如:手表的秒针1分钟走1圈。技术分享分钟之后,它与起始位置的夹角是多少?显然这个角度等于技术分享度。现在要把这个角度归化到技术分享之间。即找到一个整数技术分享,使得技术分享成立。只考虑不等式的左半部分,则有技术分享,即技术分享。显然这个夹角应该是技术分享

同样的,判断经度技术分享是否在经度技术分享和经度技术分享之间(只考虑劣弧,不考虑优弧),不能使用技术分享。如:经度180在经度-179和经度179之间,但它不满足-179 < 180 < 179。应该使用下式判断

技术分享

函数Angle360(x)将返回角度技术分享n是一个整数),且返回值在技术分享之间。显然技术分享,因此Angle360函数的C代码如下:

double Angle360(double x)

{

return x - floor(x / 360.0) * 360.0;

}

2、扩展fmod函数

上述问题里,将角度技术分享归化到技术分享之间可以使用fmod(360.0 * x,360.0);C#里可以使用(360.0 * x) % 360.0)。但是,使用fmod感觉不太方便——它的返回值符号与第一个参数的符号相同。也就是说 x 小于零,则返回值将在技术分享之间。因此有必要扩展fmod函数。

fmod(x,y)的实质是找到合适的整数技术分享,使得技术分享,然后返回余数技术分享

如果需要余数技术分享,则技术分享

如果需要余数技术分享,则技术分享

如果需要求绝对值最小的余数,则技术分享

技术分享

技术分享

fmod函数的模拟代码如下

double fmod(double x,double y)

{

y = fabs(y);

if(x >= 0.0)

{

y = x - y * floor(x / y);

}

else

{

y = x - y * ceil(x / y);

}

return y;

}

fmod函数的扩展代码如下

/****************************************************************

x / y 的余数

nFlag    [in]        1    返回的余数大于等于零

                -1    返回的余数小于等于零

                2    返回绝对值最小的余数,若同时出现 ±(y / 2) 则取正值

                -2    返回绝对值最小的余数,若同时出现 ±(y / 2) 则取负值

                0     2 相同

\****************************************************************/

double fmodEx(double x,double y,int nFlag)

{

y = fabs(y);

if(nFlag < -2)

{

nFlag = -2;

}

else if(nFlag > 2)

{

nFlag = 2;

}

switch(nFlag)

{

case 1://返回的余数大于等于 0

y = x - y * floor(x / y);

break;

case -1://返回的余数小于等于 0

y = x - y * ceil(x / y);

break;

case -2://返回的绝对值最小的余数,优先考虑 - y / 2

y = x - y * floor(x / y + 0.5);

break;

default://返回的绝对值最小的余数,优先考虑 + y / 2

y = x - y * ceil(x / y - 0.5);

break;

}

return y;

}

3、格点

现在要在区间技术分享之间插入若干点技术分享,其中n是一个整数,d是一段固定的距离(只考虑正值),如:100米、1000米……

技术分享

计算技术分享的时候要注意,不要写 for(double n = ceil(a/d);n <= floor(b/d);n++) 这样的代码,因为double是有误差的,这样会导致误差积累。应该这样:

double    n0        =    ceil(a/d);

double    x0        =    n0 * d;

int        nMax    =    (int)(floor(b/d) - n0 + 0.1);

double    x;

for(int i = 0;i <= nMax;i++)

{

    x    =    x0 + i * d;

}

下面的函数专门用来获取格点

/**********************************************************

获取区间[a,b]之间的格点,格点坐标是 d 的整数倍

x0        [out]    返回起始格点。

                 d 大于零,x0 是坐标最小的格点

                 d 小于零,x0 是坐标最大的格点

返回:获得格点的个数 nCount

格点坐标为 x0 + n * dn = 0,1,2,...nCount - 1

\**********************************************************/

long GetLatticePoints(double a,double b,double d,double*x0)

{

long nCount = 0; //格点个数

double nMin; //n 的最小值

double nMax; //n 的最大值

 

a /= d;

b /= d;

if(a > b)

{

double t;

t = a;

a = b;

b = t;

}

nMin = ceil(a);

nMax = floor(b);

if(nMax >= nMin)

{

nCount = (long)(nMax - nMin + 1.1);

if(x0)

{

*x0 = nMin * d;

}

}

return nCount;

}

 

取整函数