数学 :
如果你有一个这样的公式:
x = 3 mod 7
X可以是... -4,3,10,17,...,或者更一般地:
x = 3 + k * 7
其中,k可以是任意整数。 我也不知道模操作的是为数学定义,但是因素圈肯定是。
Python的 :
Python中,当您使用您将获得非负值%
以积极的m
:
#!/usr/bin/python
# -*- coding: utf-8 -*-
m = 7
for i in xrange(-8, 10 + 1):
print(i % 7)
结果是:
6 0 1 2 3 4 5 6 0 1 2 3 4 5 6 0 1 2 3
C ++:
#include <iostream>
using namespace std;
int main(){
int m = 7;
for(int i=-8; i <= 10; i++) {
cout << (i % m) << endl;
}
return 0;
}
将输出:
-1 0 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 0 1 2 3
ISO / IEC 14882:2003(E) - 5.6乘法运算符:
二进制/操作员产生的商,和二进制%操作者产生了由第二所述第一表达的除法的余数。 如果/或%所述第二操作数是零的行为是不确定; 否则(A / B)* B + A%b等于一个。 如果两个操作数都是非负,则剩余部分非负; 如果不是, 则余数的符号是实现定义的74)。
和
74)根据工作朝向ISO C的修订正在进行中,整数除法的优选算法遵循在ISO Fortran标准中定义的规则,ISO / IEC 1539:1991,其中,所述商数总是向零变圆。
来源: ISO / IEC 14882:2003(E)
(我无法找到一个免费版本的ISO/IEC 1539:1991
。有谁知道从哪里得到的呢?)
操作似乎是这样定义的:
问题 :
是否有意义将它定义成这样?
什么是该说明书的参数? 有没有一个地方,谁创造这样标准的人吧讨论? 我在哪里可以阅读一些有关他们为什么决定做这样说的原因是什么?
大多数时候,当我使用模,我想访问一个数据结构的元素。 在这种情况下,我必须确保国防部返回一个非负值。 因此,对于这种情况下,这将是很好的MOD总是返回非负值。 (另一个用途是欧几里德算法 。正如你可以让这两个数字正前使用这种算法,模数的符号会的问题。)
其他材料 :
参见维基百科的什么模做不同语言的一个长长的清单。
在x86(和其它处理器架构),整数除法和模数是由单一的操作,进行idiv
( div
为无符号值),这产生两个商和余数(对于字大小的参数,在AX
和DX
分别地)。 这用于在C库函数divmod
,其可被编译器优化为单个指令!
整数除法尊重两条规则:
- 非整数商正在向零舍; 和
- 等式
dividend = quotient*divisor + remainder
是由对结果满意。
因此,将一个负数由一个正数时,该商将是负的(或零)。
因此,这种行为可以被看作是当地的决策链的结果:
- 处理器指令集设计优化用于在不常见的情况(模)的一般情况(除法);
- 一致性(舍入到零,并尊重除法方程)优于数学正确性;
- Ç喜欢效率和simplicitly(尤其是考虑查看C作为“高电平汇编”的倾向); 和
- C ++更喜欢与C.兼容性
什么是该说明书的参数?
一个C ++的设计目标是有效地映射到硬件。 如果底层硬件产生负面余的方式实现了分工,那就是如果你使用你会得到什么样%
在C ++中。 这一切就是真的。
有没有一个地方,谁创造这样标准的人吧讨论?
你会发现在comp.lang.c ++和有趣的讨论。主持,程度较轻,comp.lang.c ++
早在一天,有人设计了x86指令集决定了它是正确的,好圆整数除法向零,而不是向下取整。 (也许一千骆驼巢在他母亲的胡子。的跳蚤)为了使数学的正确性,运营商REM,它的发音是“剩女”的一些外表,不得不相应的行为。 不要读这个: https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzatk/REM.htm
我警告过你。 后来有人在做C时的参数决定将它符合一个编译器做任何正确的方式或途径86。 然后,委员会在做C ++规范决定这样做的C方式。 再后来呢,这个问题被张贴后,一个C ++委员会决定在错误的方式规范。 现在,我们坚持了下来。 许多程序员写了下面的函数或类似的东西。 我可能已经做了至少十倍。
inline int mod(int a, int b) {int ret = a%b; return ret>=0? ret: ret+b; }
有去您的工作效率。
这些天,我使用实质上包含以下,具有一定的type_traits东西扔了进去。(感谢为更清晰给了我使用后者天C ++的改进的想法评论。见下面)。
<strike>template<class T>
inline T mod(T a, T b) {
assert(b > 0);
T ret = a%b;
return (ret>=0)?(ret):(ret+b);
}</strike>
template<>
inline unsigned mod(unsigned a, unsigned b) {
assert(b > 0);
return a % b;
}
真正的事实:我游说帕斯卡尔标准委员会做MOD的正确方法,直到他们心软。 我的恐惧,他们没有整数除法错误的方式。 因此,他们甚至不匹配。
编辑:更清晰的给了我一个想法。 我工作的一个新的。
#include <type_traits>
template<class T1, class T2>
inline T1 mod(T1 a, T2 b) {
assert(b > 0);
T1 ret = a % b;
if constexpr ( std::is_unsigned_v<T1>)
{
return ret;
} else {
return (ret >= 0) ? (ret) : (ret + b);
}
}