为什么用模时做C ++输出负数?(Why does C++ output negative numb

2019-06-17 12:59发布

数学

如果你有一个这样的公式:

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总是返回非负值。 (另一个用途是欧几里德算法 。正如你可以让这两个数字正前使用这种算法,模数的符号会的问题。)

其他材料

参见维基百科的什么模做不同语言的一个长长的清单。

Answer 1:

在x86(和其它处理器架构),整数除法和模数是由单一的操作,进行idivdiv为无符号值),这产生两个商和余数(对于字大小的参数,在AXDX分别地)。 这用于在C库函数divmod ,其可被编译器优化为单个指令!

整数除法尊重两条规则:

  • 非整数商正在向零舍; 和
  • 等式dividend = quotient*divisor + remainder是由对结果满意。

因此,将一个负数由一个正数时,该商将是负的(或零)。

因此,这种行为可以被看作是当地的决策链的结果:

  • 处理器指令集设计优化用于在不常见的情况(模)的一般情况(除法);
  • 一致性(舍入到零,并尊重除法方程)优于数学正确性;
  • Ç喜欢效率和simplicitly(尤其是考虑查看C作为“高电平汇编”的倾向); 和
  • C ++更喜欢与C.兼容性


Answer 2:

什么是该说明书的参数?

一个C ++的设计目标是有效地映射到硬件。 如果底层硬件产生负面余的方式实现了分工,那就是如果你使用你会得到什么样%在C ++中。 这一切就是真的。

有没有一个地方,谁创造这样标准的人吧讨论?

你会发现在comp.lang.c ++和有趣的讨论。主持,程度较轻,comp.lang.c ++



Answer 3:

早在一天,有人设计了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);
    }
}


文章来源: Why does C++ output negative numbers when using modulo?