Search code examples
pythonc++modulosigned

Python code doesn't work like it does in C++


How to get the same values ​​in Python as in C++?

CPP code

#include <bitset>
#include <iostream>

using namespace std;

int main() {
    short int divider = -32768;
    auto divider_bin_str = bitset<16>(divider).to_string();
    cout << "divider: " << divider << " " << divider_bin_str << endl; // divider: -32768 1000000000000000

    char division = static_cast<char>(divider % 3000);
    string division_bin_str = bitset<8>(division).to_string();
    cout << "division: " << (int) division << " " << division_bin_str << endl; // division: 48 00110000
}

Python code

divider = -32768
print(f'divider: {divider} {bin(divider)}')  # divider: -32768 -0b1000000000000000
division = divider % 3000

print(f'division: {division} {bin(division)}')  # division: 232 0b11101000

I couldn't think of anything better than calling C code from Python :)


Solution

  • As quoted in Why does C++ output negative numbers when using modulo?

    ISO/IEC 14882:2003(E) - 5.6 Multiplicative operators:

    The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first expression by the second. If the second operand of / or % is zero the behavior is undefined; otherwise (a/b)*b + a%b is equal to a. If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined

    So here your C++ compiler computes

    -32768 % 3000  = -2768
    

    then wrapping of char type (signed/unsigned? again implementation defined)

    -2768 wrapped around 256 = 48 (< 127 so no issue here)
    

    The corresponding python code (python doesn't return a negative result in that case, by design) is:

    divider = -32768
    
    division = (divider % 3000)
    if divider < 0:
        division -= 3000
    
    result = division % 256
    
    if result > 127:  # if signed char (no difference in that case)
        result = 256-result
    
    print(division % 256)
    

    prints

    48

    Given the implementation defined aspect, I suggest that you test this C++ and python code against a lot of test cases, for example with values > 127 when casting to char, also if you change compiler options or the compiler itself.