取余与取模
取余
取余运算,就是取左侧运算数除右侧运算数的余数的运算。
例如10取余3,商3余1,取余运算就是要余数的值,也就是取余结果为1。
如果除数是负数,也是一样的运算方法。
例如10取余**-3**,商**-3余1**,取余结果为1。
所以我们可以得知取余结果 = 左侧数 - 左侧数除右侧数的商 * 右侧数。
//取余
//left 左操作数
//right 右操作数
//return 取余结果
template<class T>
T GetMod(T left, T right) {
if (right == 0)
throw exception("右操作数不能为0");
return left - (int) (left / right) * right;
}
C++语言实现的%运算符,不支持浮点型的取余,笔者自实现的取余只是多了浮点型的运算扩展,目前不清楚什么场景会用到浮点型的取余。
取模
取模运算,是对数的范围加一个限制。
类似于钟表,从12时开始,顺时针转5小时、顺时针转17小时、逆时针转7小时,都是5时,不管转多少,显示的值都在十二小时之内。
例如钟表,5 取模 12,取模结果为5,与取余一样
17 取模 12,取模结果为5,与取余一样
-7取模 12,取模结果为5,取余结果为-7。
所以取模就是对左侧运算数加了一个限制,限制在区间[0,右侧运算数)或(右侧运算数,0],这取决于右侧运算数的正负。
如果左右操作数符号一致,那么运算结果与取余一样,
left - (int)(left / right) * right;
如果左右操作符号不一致,那么我们取模的结果 = 取余结果 + 右操作数(取余结果不为0)。
left - (int)(left / right) * right + right;
//可改为
left - ((int)(left / right) - 1) * right
如果左右操作符号不一致,那么我们取模的结果 = 取余结果(取余结果为0)。
left - (int)(left / right) * right;
可根据上述三式的不同部分,得知我们要对left / right的浮点结果,进行左取值。
//取模
//left 左操作数
//right 右操作数
//return 取模结果
template<class T>
T GetModulo(T left, T right) {
if (right == 0)
throw exception("右操作数不能为0");
return left - floor((float) left / right) * right;
}
C++语言似乎没有取模运算,这是笔者自实现的取模运算,支持浮点型的取模运算。
整理
#pragma once
class EMath {
public:
//取余
//left 左操作数
//right 右操作数
//return 取余结果
template<class T>
static T GetMod(T left, T right) {
if (right == 0)
throw exception("右操作数不能为0");
return left - (int) (left / right) * right;
}
//取模
//left 左操作数
//right 右操作数
//return 取模结果
template<class T>
static T GetModulo(T left, T right) {
if (right == 0)
throw exception("右操作数不能为0");
return left - floor((float) left / right) * right;
}
};
使用案例
int main() {
cout << EMath::GetMod<float>(10, 1) << endl;
cout << EMath::GetModulo<double>(-12, 0) << endl;
return 0;
}