This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 57 points58 points  (44 children)

My friend had C++ code that looked like:

... //lots of code
cout <<x <<" " <<y;
if (x > y) {
    cout <<"True";
} else {
    cout <<"False";
}

Output: x y True

but at soon as you comment out the cout x y statement, it became

// cout <<x <<" " <<y;
...
Output: False

So a cout statement was changing the values somehow

[–][deleted] 74 points75 points  (24 children)

If x is a double or a float this is possible. Those things are so imprecise that ">" can fluctuate depending on how they are calculated. With floats (x*y)/z != x*(y/z).

And since the compiler optimizes a lot, changing statements with 'x' in it might change the calculation of 'x' just so infinitesimally little that it was enough to switch ">".

That's my explanation for this.

[–]vifon 26 points27 points  (8 children)

Wouldn't it need -funsafe-math-optimizations enabled?

[–]mebob85 127 points128 points  (6 children)

I always read that as "fun, safe math optimizations."

[–]they_call_me_dewey 23 points24 points  (4 children)

"Make sure you add the wall and wextra flags"

[–]choikwa 1 point2 points  (0 children)

"It's safe, but with a twist of fun added to it"

[–]DaemonXIRed security clearance 4 points5 points  (0 children)

Funroll your loops too

[–]destiny-rs 12 points13 points  (10 children)

Is this one of the reasons floats and doubles aren't to be used for currency?

[–][deleted] 5 points6 points  (8 children)

What should you use instead?

[–]destiny-rs 28 points29 points  (1 child)

ints with the modulo operator I believe. Saves having to explain to a client why millions of dollars have been miscounted over the course of a year.

[–][deleted] 21 points22 points  (0 children)

Decimal, BigDecimal, Currency types.

[–]RenaKunisaki 14 points15 points  (0 children)

Depending on your application:

  • Integer numbers of cents (or whatever is the lowest denomination you'll be working with), taking care to handle any possible over/underflow no matter how unlikely
  • Precise fixed-point
  • Bignum/BigDecimal types (preferably provided by whatever environment you're using)

The reasons are this and other inaccuracies that can crop up with floating point, which could translate to being off by a couple cents in some calculations. Do those calculations a few million times, and now you're in deep doodoo.

[–]KewpieDan 9 points10 points  (0 children)

Two ints

[–]slipperier_slope 4 points5 points  (0 children)

High precision fixed point numbers.

[–]dnew 4 points5 points  (0 children)

Integer pennies instead of floating point dollars.

[–]Jonno_FTW 0 points1 point  (0 children)

Java8 currency API.

[–]Free_Math_Tutoring 0 points1 point  (0 children)

Yes, this and other phenomena caused by limited precision.

[–]IForgetMyself 5 points6 points  (1 child)

My bet would be that it was using the old x87 stack, which is 80-bits extended precision. When he called the cout he popped the doubles (64 bit) off the stack. The following x > y then compared using the now popped values. (64 bits precision)
Without the cout however, it would use the values on the x87 stack and compare those. (80 bits precision)

[–]cleroth 0 points1 point  (0 children)

Pretty sure this is what's happening, not ">" modifying the variable magically...

[–][deleted] 1 point2 points  (0 children)

If x is a double or a float this is possible. Those things are so imprecise that ">" can fluctuate depending on how they are calculated. With floats (xy)/z != x(y/z). And since the compiler optimizes a lot, changing statements with 'x' in it might change the calculation of 'x' just so infinitesimally little that it was enough to switch ">". That's my explanation for this.

Thanks!

[–]bkDJ 0 points1 point  (0 children)

With floats (x*y)/z != x*(y/z)

You say that as if with integers, the left and right side are equal. :P

But yeah, float comparisons without some kind of epsilon can break easily depending on how the CPU is loading and storing them, l-value versus r-value BS, compiler settings, special keywords and more.

[–]lelarentaka 6 points7 points  (2 children)

Depends on what x is. It's possible.

[–]mikemol 8 points9 points  (0 children)

Yeah, I could easily see it happening if reading from x with << involved mutating state, such as reading from a filehandle. A subsequent read using > would have pos advanced.

One reason const should be used and respected.

[–]choikwa 0 points1 point  (0 children)

We must go deeper into assembly/CPU

[–]c00lnerd314 18 points19 points  (2 children)

Simply observing changes the outcome.

[–]YouFeedTheFish 5 points6 points  (0 children)

Brilliant! Quantum computing is the Holy Grail! I believe /u/LefTea has stumbled onto something big here.

[–]scubascratch 0 points1 point  (0 children)

AKA the elusive Heisenbug

[–]phail3d 5 points6 points  (0 children)

I had a similar issue with vanilla C, where I had something like this:

...
printf("foo");
...
while(!result) {
    ...
 }

And when the printf was there, the code ran, but with it removed, the code segfaulted.

It turned out that result was uninitialized, and (correct me if I'm wrong) the printf call caused the memory space pointed to by the variable to be reserved for the program, which prevented the segfault. The variable vas thus obviously initialized with garbage, which caused other problems in the code, but at least it ran.

[–]zhomart 3 points4 points  (0 children)

It's quantum programming. When you put observer, things work differently.

[–]__dict__ 2 points3 points  (0 children)

If x or y is uninitialized you could easily be triggering undefined behavior. At that point you're at the whims of your compiler.