-2

I have the following sample code which I am compiling and executing on x86_64 and aarch64 platforms but ending up with different outputs.

#include <iostream>

int main()
{
    double d = 2147483649;
    int i = d;

    std::cout << i << std::endl;

    return 0;
}

Output on x86_64: -2147483648 Output on aarch64: 2147483647

Why there is a difference in output on both the architectures. Is there any option I need to pass to the compiler in case of aarch64 to make the behavior consistent to that of x86_64?

I tried compiling the code as following "g++ a.cpp -o a.o" on both the architectures. And I am expecting to return the same value of "i" on both the architectures.

  • 1
    _Undefined behavior_ maybe? – πάντα ῥεῖ Jun 03 '23 at 18:55
  • You cannot make undefined behaviour consistent, not even if you're using only a single compiler. Instead you need to avoid it by doing a check, e.g. `int i; if (d > std::numeric_limits::max()) { ... } else if (d < std::numeric_limits::min()) { ... } else { i = d; }` – fabian Jun 03 '23 at 19:00
  • 1
    Does this answer your question? [Handling overflow when casting doubles to integers in C](https://stackoverflow.com/questions/526070/handling-overflow-when-casting-doubles-to-integers-in-c) – fabian Jun 03 '23 at 19:03
  • Similar to a simple int underflow or overflow. Both are UB. C++ provides few/no guarantees except for unsigned int types. – doug Jun 03 '23 at 19:04
  • What do you want to happen when the `double` cannot be converted to an `int`? Make it `0`? Make it `-1`? Throw an exception? Terminate the program? *I am expecting to return the same value* I do not see anything in the provided code than ensures the failed conversion will result in the same value. – Eljay Jun 03 '23 at 19:55
  • To avoid this undefined behavior, and to optimize `floor` or `round` *that you should nearly always use when converting `double` to integers*, I wrote a template function which is basically implemented like that: `template inline I floor_cast(F value) { int64_t w = static_cast(value); return static_cast(w - (value < w)); }`. Rationale: a `double` has 53 bits of mantissa, converting it to a 64-bit integer is always possible without losing information (after rounding). And then the conversion to the desired integer type is defined using modulo arithmetic. – prapin Jun 03 '23 at 20:28

1 Answers1

2

Such a conversion is undefined behaviour, and thus, the compiler can do whatever it wants.

Per [conv.fpint],

A prvalue of a floating-point type can be converted to a prvalue of an integer type. The conversion truncates; that is, the fractional part is discarded. The behavior is undefined if the truncated value cannot be represented in the destination type.

ChrisMM
  • 8,448
  • 13
  • 29
  • 48