Why doesn't a negative number modulo a vector size give a negative number? [duplicate]

点点圈 提交于 2020-07-03 05:45:11

问题


#include <iostream>
#include <string>
#include <vector>

using namespace std;

int main()
{
  vector<int> v = {1, 2, 3, 4, 5, 6, 7};
  int i = -4;

  cout << i << endl;
  cout << v.size() << endl;
  cout << i % v.size() << endl;
  cout << -4 % 7 << endl;
}

The above code prints:

-4
7
5
-4

Can someone please explain why i % v.size() prints 5 instead of -4? I'm guessing it has something to do with vector.size(), but unsure what the underlying reasoning is. Thanks in advance.


回答1:


The operands of % undergo the usual arithmetic conversions to bring them to a common type, before the division is performed. If the operands were int and size_t, then the int is converted to size_t.

If size_t is 32-bit then -4 would become 4294967292 and then the result of the expression is 4294957292 % 7 which is actually 0.

If size_t is 64-bit then -4 would become 18,446,744,073,709,551,612 and the result of this % 7 is 5 which you saw.

So actually we can tell from this output that your system has 64-bit size_t.




回答2:


In C++ the modulus operator is defined so that the following is true for all integers except for b == 0:

(a/b)*b + a%b == a

So it is forced to be consistent with the integer division, which from C++ 11 onwards truncates to zero even for negative numbers. Hence everything is well defined even for negative numbers.

However, in your case you have an signed / unsigned division (because .size() returns unsigned) and the usual signed/unsigned rules apply. This means that in this case all arguments are converted to unsigned before the operation is carried out (see also Ruslan's comment).

So -4 is converted to unsigned (and becomes a very large number) and then modulo is carried out.

You can also see this as 5 is not a correct answer for -4 modulo 7 with any definition of integer division (3 would be correct).

Arithmetic rules with C and C++ are not intuitive.




回答3:


Because v.size return size_t.

cout << -4 % size_t(7) << endl; // 5

Take a look modulo-operator-with-negative-values

UPD: and signed-int-modulo-unsigned-int-produces-nonsense-results




回答4:


This is due to the type of v.size(), which is an unsigned type. Due to integer promotion, this means that the result will also be treated as unsigned, despite i being a signed type.

I am assuming you are compiling on 64 bit. This means that in addition to promotion to unsigned, the result will also be of the 64 bit type unsigned long long. Step by step:

  1. unsigned long long _i = (unsigned long long)-4; // 0xFFFFFFFFFFFFFFFC!
  2. unsigned long long result = _i % (unsigned long long)7; // 5

Since presumably you want to preserve the signedness of i, in this case it is enough to cast v.size() to a signed type to prevent the promotion to unsigned: i % (int)v.size() will give -4.




回答5:


From cppreference on Usual arithmetic conversions and C++ standard

Otherwise (the signedness is different): If the unsigned type has conversion rank greater than or equal to the rank of the signed type, then the operand with the signed type is implicitly converted to the unsigned type.

-4 is signed and 7 is size_t which is an unsigned type, so -4 is converted to unsigned first and then modulus is carried out.

With that mind, if you break it down, you will immediately see what is happening:

size_t s = -4; // s = 18446744073709551612 on a 64 bit system
size_t m = 7;
std::cout << s % m << '\n'; //5

The results might be different for a 32-bit system.

cout << -4 % 7 << endl; still prints -4. Why? It's because the type of both -4 and 7 is int.

C++ standard §5.13.2.3 Type of an integer literal

The type of an integer-literal is the first type in the list in Table 8 corresponding to its optional integer-suffix in which its value can be represented. An integer-literal is a prvalue.

Table 8: Types of integer-literals without suffix:

    int
    long int
    long long int

So, -4 and 7 both are int in this case and hence the result of modulo is -4.



来源:https://stackoverflow.com/questions/62382318/why-doesnt-a-negative-number-modulo-a-vector-size-give-a-negative-number

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!