aloysiustanrs
aloysiustanrs

Reputation: 39

C++ modulo returning inconsistent results

Can someone tell me why these two functions return different results?

After running code

#include <string>
#include <stdio.h>
#include <iostream>
using namespace std;

int returnN(string s, int n)
{
    int newN = n % s.size();
    return newN;
}

int returnN2(string s, int n)
{
    int a = s.size();
    int newN = n % a;
    return newN;
}

int main(void)
{
    string text2 = "Hello World!";
    cout << returnN(text2, -2) << endl;
    string text3 = "Hello World!";
    cout << returnN2(text3, -2) << endl;
}

returnN(text2, -2) returns 2

returnN2(text3, -2) returns -2

PS D:\src\cpp> g++ --version
g++.exe (Rev3, Built by MSYS2 project) 13.2.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

I tried to debug and see why but I still cant figure out why

Upvotes: 3

Views: 196

Answers (2)

wohlstad
wohlstad

Reputation: 29009

Can someone tell me why these two functions return different results?

s.size() returns a size_t which is unsigned.

The difference between returnN and returnN2 is in the types of the operands used for the modulo calculation:

  1. In returnN you performs a modulo with an unsigned value (s.size()).
    This means that the value of n is converted to unsigned as well to perform the modulo.
    The result of the conversion is implementation defined, but should be equal to the max value of size_t minus 1, i.e. a very large positive value.
    The modulo of this large postive value with s.size() turns out to be 2.
  2. In returnN2 you first assign s.size() to int a (which is signed), and then perform the modulo with the signed values.
    The value of n stays as is (-2), and the result is -2.

Your compiler should alert you about the issue.
MSVC for example issues the following warning for initializing a:

warning C4267: 'initializing': conversion from 'size_t' to 'int', possible loss of data

A side note:
It's better to avoid using namespace std; - see What's the problem with "using namespace std;"?.

Upvotes: 4

Shelton Liu
Shelton Liu

Reputation: 601

Can someone tell me why these two functions return different results?

Why returnN(text2, -2) returns 2 is that s.size() returns a value of type size_t, which is an unsigned integer type. So, When n is used in the modulus operation with s.size(), it promotes n to an unsigned integer type, causing a conversion from a negative number to a large positive number. That’s why get 2 as the result.

However, in returnN2, s.size() is explicitly assigned to the variable a, which is of type int. So, the % operation here performs signed integer modulus. That’s why get -2 as the result.

Upvotes: 1

Related Questions