Actually with C / C++, it can be different even with the same chip. It can actually be different using the same binary and still be compliant.
Something like this:
if( a == x/y )
assert( a == x/y );
Is allowed to assert (!). It's also allowed to not assert. Worse, the following is a legal "optimization" of the above code:
if( a == x/y )
if ( getRandomBooleanFromSomewhere() )
assert( a == x/y );
(I'd use rand, but I don't want to get into matters of state here. Just assume that getRandomBooleanFromSomewhere, well, pulls a random boolean from somewhere. No side effects.)
Why, you might ask? It's allowed to use extra precision, but not required to. And it's not required to even be consistent about it. So: if it uses extra precision, and it decides to lose the extra precision (say, by spilling x/y to stack) between the first and second uses, the assert could potentially fire. If it doesn't do both of those, the assert cannot fire. So it's legal to remove the assert, but also legal to keep it. And also legal to randomly decide which to do at runtime.
Now, this is a stupid thing for it to do in this case. But nonetheless, it is allowed. And there are cases where analogous optimizations actually make a plausible amount of sense.
You can work around it to an extent with FPU flags. But that way lies madness. To put it mildly. ("It desyncs when I print a document.")
AIUI the C standard mostly regards floating-point as out of scope / platform-specific. Your vendor should (hopefully) provide stricter specs for how it works on your particular machine.