Mar*_*oma 52 c++ standards modulo
数学:
如果你有这样的等式:
x = 3 mod 7
Run Code Online (Sandbox Code Playgroud)
x可以是...... -4,3,10,17 ......,或更一般地:
x = 3 + k * 7
Run Code Online (Sandbox Code Playgroud)
其中k可以是任何整数.我不知道为数学定义了模运算,但因子环肯定是.
Python:
在Python中,当您使用%正数时,您将始终获得非负值m:
#!/usr/bin/python
# -*- coding: utf-8 -*-
m = 7
for i in xrange(-8, 10 + 1):
print(i % 7)
Run Code Online (Sandbox Code Playgroud)
结果是:
6 0 1 2 3 4 5 6 0 1 2 3 4 5 6 0 1 2 3
Run Code Online (Sandbox Code Playgroud)
C++:
#include <iostream>
using namespace std;
int main(){
int m = 7;
for(int i=-8; i <= 10; i++) {
cout << (i % m) << endl;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
将输出:
-1 0 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 0 1 2 3
Run Code Online (Sandbox Code Playgroud)
ISO/IEC 14882:2003(E) - 5.6乘法运算符:
二元/运算符产生商,二元%运算符从第一个表达式除以第二个表达式得到余数.如果/或%的第二个操作数为零,则行为未定义; 否则(a/b)*b + a%b等于a.如果两个操作数都是非负的,那么余数是非负的; 如果没有,余数的符号是实现定义的74).
和
74)根据正在进行的ISO C修订工作,整数除法的首选算法遵循ISO Fortran标准ISO/IEC 1539:1991中定义的规则,其中商始终向零舍入.
(我找不到免费版ISO/IEC 1539:1991.有人知道从哪里获取它吗?)
该操作似乎定义如下:

问题:
这样定义它是否有意义?
这个规范的论据是什么?是否存在创建此类标准的人员讨论它的地方?在哪里我可以读到他们决定这样做的原因?
大多数时候,当我使用modulo时,我想访问数据结构的元素.在这种情况下,我必须确保mod返回一个非负值.因此,对于这种情况,mod总是会返回一个非负值.(另一种用法是欧几里得算法.因为你可以在使用这个算法之前使两个数字都为正数,所以模数的符号很重要.)
附加材料:
有关modulo在不同语言中的作用,请参阅Wikipedia.
eca*_*mur 27
在x86(和其他处理器体系结构)上,整数除法和模数由单个操作执行idiv(div对于无符号值),它产生商和余数(对于字大小的参数,分别为AX和DX).这在C库函数中使用divmod,可以由编译器优化为单个指令!
整数部门遵守两条规则:
dividend = quotient*divisor + remainder结果满足等式.因此,当将负数除以正数时,商将为负(或零).
所以这种行为可以看作是一系列地方决策的结果:
fre*_*low 10
这个规范的论据是什么?
C++的设计目标之一是有效地映射到硬件.如果底层硬件以产生负余数的方式实现除法,那么如果你%在C++中使用它就会得到.这就是真的.
是否存在创建此类标准的人员讨论它的地方?
您将在comp.lang.c ++.moderated以及在较小程度上comp.lang.c ++上找到有趣的讨论
Jiv*_*son 10
回到那一天,设计x86指令集的人认为将整数除法舍入为零而不是向下舍入是正确和好的.(可能是一千只骆驼的跳蚤在他母亲的胡子里筑巢.)为了保持一些数学正确性,操作员REM(发音为"余数")必须相应地表现.请勿阅读:https://www.ibm.com/support/knowledgecenter/ssw_ibm_i_73/rzatk/REM.htm
我警告过你.后来有人做了C规范,认为它可以符合编译器以正确的方式或x86方式进行.然后一个做C++规范的委员会决定用C方式做.然后,在发布这个问题之后,C++委员会决定以错误的方式进行标准化.现在我们坚持下去了.许多程序员编写了以下函数或类似的东西.我可能已经完成了至少十几次.
inline int mod(int a, int b) {int ret = a%b; return ret>=0? ret: ret+b; }
Run Code Online (Sandbox Code Playgroud)
你效率很高.
这些天我基本上使用了以下内容,其中包含了一些type_traits内容.(感谢Clearer的评论让我对使用后期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;
}
Run Code Online (Sandbox Code Playgroud)
真实的事实:我游说帕斯卡标准委员会以正确的方式进行调整,直到他们妥协.令我恐惧的是,他们以错误的方式进行整数除法.所以他们甚至不匹配.
编辑:清洁工给了我一个主意.我正在研究一个新的.
#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);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
20429 次 |
| 最近记录: |