负数模数向量大小为什么不给负数?[重复]

问题描述 投票:8回答:5
#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;
}

上面的代码打印出来了。

-4
7
5
-4

谁能解释一下为什么?i % v.size() 印花 5 而不是 -4? 我猜测它与以下内容有关 vector.size(),但不知道根本原因是什么。先谢谢你了。

c++ modulus integer-promotion
5个回答
28
投票

的操作数 % 经历 常规算术转换 以使它们达到一个共同的类型,然后再进行分割。 如果操作数是 intsize_t那么 int 转换为 size_t.

如果 size_t 是32位,那么 -4 将成为 4294967292 然后表达式的结果是 4294957292 % 7 这其实 0.

如果 size_t 是64位,那么 -4 将成为18,446,744,073,709,551,612,而这一结果将是 % 75 你也看到了。

所以实际上我们可以从这个输出中看出,你的系统有64位的size_t。


8
投票

在C++中,模数运算符的定义是这样的,所以对于以下情况是真的 整数,除了b==0。

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

所以它必须和整数除法保持一致, 从C++ 11开始, 即使是负数也要截断为零. 因此,即使是负数,一切都很好定义。

然而,在你的例子中,你有一个有符号的无符号除法(因为.size()返回无符号),通常的signedunsigned规则适用。这意味着在这种情况下,所有的参数都会在操作执行之前被转换为无符号数(参见Ruslan的评论)。

所以-4被转换为无符号(并成为一个非常大的数字),然后进行modulo运算。

你也可以看到这一点,因为在任何整数除法的定义中,5都不是-4模数7的正确答案(3才是正确的)。

用C和C++的算术规则并不直观。


4
投票

因为 v.size 返回 size_t.

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

你看一下 负值模数运算器

UPD:和 Signed-int-modulo-unsigned-int-produce-nonsense-results(无意义的结果)


3
投票

这是因 v.size(),这是一个无符号类型。由于整数的提升,这意味着结果也将被视为无符号类型,虽然 i 是一个有符号的类型。

我假设你是在64位上编译的。这意味着除了升级为无符号类型外,结果也将是64位的类型。unsigned long long. 一步一步来。

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

因为你大概想保存这些东西的签名性 i在这种情况下,只需投下 v.size() 到已签署的类型,以防止升级到未签署的类型。i % (int)v.size() 会给 -4.


1
投票

从cppreference上看 通常的算术转换C++标准

否则(签名性不同)。如果无符号类型的转换等级大于或等于有符号类型的等级,那么有符号类型的操作数将隐式转换为无符号类型。

-4signed7size_t 这是 unsigned 型,所以 -4 转换为 unsigned 先进行模数,再进行模数。

有了这样的想法,如果你把它分解开来,你就会立刻明白发生了什么。

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

对于32位系统来说,结果可能是不同的.

cout << -4 % 7 << endl; 仍然打印 -4. 为什么呢?因为这两种类型的 -47int.

C++标准§5.13.2.3 整数文字的类型

整数字词的类型是表8中列表中的第一个类型,对应于它的可选整数后缀,它的值可以用它来表示。一个整数字词是一个prvalue。

表8:整数字的类型 无后缀。

    int
    long int
    long long int

所以: -47 都是 int 在这种情况下,因此modulo的结果是 -4.

© www.soinside.com 2019 - 2024. All rights reserved.