【问题标题】:Modulus using string size weird behavior使用字符串大小奇怪行为的模数
【发布时间】:2020-04-15 01:50:41
【问题描述】:

请解释为什么代码的第一个 sn-p 不会导致 -1。

    string s = "abc";
    int amount = -1;
    cout << "amount to shift before modulus: " << amount<<endl;
    amount %= s.size();
    cout << "mod " <<s.size()<<endl;
    cout << "amount to shift after modulus: " << amount<<endl;

输出:
模数前的偏移量:-1
模组 3
模数后移位量:0

    string s = "abc";
    int sSize = s.size();
    int amount = -1;
    cout << "amount to shift before modulus: " << amount<<endl;
    amount %= sSize;
    cout << "mod " <<sSize<<endl;
    cout << "amount to shift after modulus: " << amount<<endl;

输出:
模数前的偏移量:-1
模组 3
模数后的位移量:-1

当我遇到这种行为时,我正在完成编码挑战,但我不明白发生了什么。如果金额为正数(例如 1),则不会发生此行为。

【问题讨论】:

  • 我计算了数字,这是真的,这就是二进制补码数学在 64 位平台上的结果。然而,解释这里发生的事情只会鼓励更多由那些无用的在线上下文网站产生的这类问题,而那些低质量的问题真的应该被劝阻。这里的噪音已经太大了。
  • @Sam:这个问题是通常算术转换的结果。我找不到似乎合适的副本,而且我认为这个问题不够明显,需要回答。
  • 对不起,让我澄清一下。问题是 -1 mod 3 和 -1 mod s.size() 之间的差异(也是 3)导致两个不同的结果。
  • @calamari:是的,3 在两种计算中是相同的。不同的是 -1。

标签: c++ string modulo


【解决方案1】:

如果在有符号整数和无符号整数之间进行算术运算(包括算术比较),并且无符号整数类型至少与有符号整数一样宽,那么有符号整数被转换为无符号整数。 (这就是所谓的"usual arithmetic conversions"的结果。)

这几乎总是会产生意想不到的结果,除非算术运算是加法或减法。在许多情况下,如果您请求警告,一个好的编译器会警告您执行混合符号算术。 (强烈推荐!)这只是一种相对不常见的变体。

在第一种情况下,s.size()size_t 类型,这是一个无符号类型,可能是 64 位;因此,它比int 更宽。因此,为了计算 amount % s.size(),编译器首先将 amount 转换为无符号 size_t,这将导致 264-1。碰巧,这个数字可以被 3 整除,所以模运算返回 0。

在第二种情况下,您强制将 s.size() 转换为有符号整数。由于该值肯定在int 的范围内,因此转换是明确定义的。随后的模运算在 ints 上执行,它们是有符号的,如果您希望有符号的模以它在 C++ 中的方式工作,则会产生预期的结果。 (有关更多信息,请参阅Why does C++ output negative numbers when using modulo?。)

【讨论】:

  • 谢谢!你的回答很有道理。
猜你喜欢
  • 1970-01-01
  • 2019-03-17
  • 2011-03-30
  • 2017-12-31
  • 2021-07-02
  • 1970-01-01
  • 1970-01-01
  • 2023-03-20
相关资源
最近更新 更多