1

I was working on college stuff and I wondered of the difference between this:

double TComplejo::Mod(void) const
{
    double a = sqrt(re * re + im * im);
    return a;
}

and this:

double TComplejo::Mod(void) const
{
    return sqrt(re * re + im * im);
}

Both re and im are doubles.

I was warned that "Second code snippet could reside in a decimal precision issue".

wohlstad
  • 12,661
  • 10
  • 26
  • 39
  • 5
    There is no difference. In fact it's very likely that the two alternatives will compile to exactly the same machine code. Who ever warned you did not know what they were talking about. – john Feb 01 '23 at 09:23
  • @john nrvo makes a difference, but I suppose its ok to say that there is none – 463035818_is_not_an_ai Feb 01 '23 at 09:24
  • @john not a c++ programmer, but perhaps it was the distinction between lvalues / rvalues? – Tasos Papastylianou Feb 01 '23 at 09:24
  • 4
    "I was warned it would cause some strange behavior." you need to ask the person that told you that what they meant. In the posted code there is absolutely no reason to expect something "strange" happening. – 463035818_is_not_an_ai Feb 01 '23 at 09:25
  • There can be a difference when the return type is class type. Since C++17 second version is guaranteed to have copy elision and in the first it's possible, but not guaranteed. For `double`, john is right, its unlikely that compiler will generate different assembly for both functions. – Yksisarvinen Feb 01 '23 at 09:26
  • To be clear, there's no difference in functionality, and certainly no 'strange behaviour' but it's possible there's a difference in efficiency (although I'd be surprised). – john Feb 01 '23 at 09:27
  • 2
    in general if someone tells you "Do X because of Y" it is actually more imortant to understand why they said Y rather than the X. (and if there is no Y then very likely X is nonsense) – 463035818_is_not_an_ai Feb 01 '23 at 09:27
  • This should answer large part of your question https://stackoverflow.com/questions/15718262/what-exactly-is-the-as-if-rule – 463035818_is_not_an_ai Feb 01 '23 at 09:29
  • @463035818_is_not_a_number in their own words: "Second code snippet could reside in a decimal precision issue" No idea why. – Mario Davó Feb 01 '23 at 09:39
  • 2
    you should clarify that in the quesiton. Though, the answer is still "no". Only the person knows why they think returning a `double` rather than returning a `double` would result in a precision issue, or maybe you misunderstood what they said – 463035818_is_not_an_ai Feb 01 '23 at 09:41
  • btw there is a different very subtle issue when calling functions coming from c without the `std::` prefix when c++ added overloads. There are cases where you can get a different function called than what you expect. However, thats no issue here, because c++ added the `float` overload while the c function for `float` is `sqrtf`. – 463035818_is_not_an_ai Feb 01 '23 at 09:52
  • Any compiler from the last few decades will produce exactly the same code for both. Note however that for instance `double res = re * re; double ims = im * im; double sum = res + ims; return sqrt(sum);` *may* produce a different result from both of those on a machine where intermediate results can be wider than a `double`. Perhaps the person you were talking to had something like that in mind. – molbdnilo Feb 01 '23 at 09:58
  • @molbdnilo: the reasoning must be refined: whether the intermediate result is stored then returned as a double or immediately returned as a double makes no difference. The only way is if the value is actually not *returned* as a double. –  Feb 01 '23 at 10:18
  • also this is not C so change `double TComplejo::Mod(void) const` to `double TComplejo::Mod() const` – bolov Feb 01 '23 at 10:21
  • Difference I see is for debugging: breakpoint, and value of `a` directly available. (Some debuggers also show returned value though). – Jarod42 Feb 01 '23 at 13:50

2 Answers2

3

There is no real difference between the 2 code snippets:

  1. The precision aspect:
    Both snippets deal only with doubles (with no conversion).
    Storing the double expression in a variable and then returning it is identical sematically to returning it directly.

  2. The performance aspect:
    Due copy-elision (RVO) the generated asembly code is likely to be the same with modern compilers. Even before C++17 with mandatory copy elision, most compilers would produce the same code for the 2 snippets.

For example: as you can see here (Godbolt) GCC (with -O2) produces the same code for both snippets.

This post discussing What exactly is the "as-if" rule? contains some more relevant info that should make it clear why the 2 snippets should behave the same.

wohlstad
  • 12,661
  • 10
  • 26
  • 39
2

From a pure semantic point of view, the two codes have absolutely the same effect. The modulus is computed as a double-precision number. Whether it is temporarily stored in a double variable or not makes no difference. By the way, the optimizing compiler will most probably implement the first version like the second, recognizing that the temporary storage is useless.

Anyway, from a pragmatic point of view a difference could exist on the x86/x64 platform where the FPU registers are 80 bits rather than 64. In some optimization modes, the data is kept in those registers rather than copied back to memory with rounding. So the 80 bits computed value could be used straight from the FPU register for the next computations.

Anyway, it is unlikely that in this circumstance, using a temporary will force rounding to 64 bits. In any case, the second form could only be more accurate.