22

I understand floating point has rounding errors, but I'm wondering if there are certain situations where the error does not apply, such as multiplication by zero .

Does zero times any number = zero for all floating points ?

chqrlie
  • 131,814
  • 10
  • 121
  • 189
Thomas
  • 6,032
  • 6
  • 41
  • 79
  • 4
    Apart from special values like NaN, Infinity or -Infinity, you are correct to assume that any normal number multiplied by exact zero produces exactly zero. – Daniel Frey May 14 '15 at 16:20

2 Answers2

28

False:

0f * NAN == NAN
0f * INFINITY == NAN

and ...

0f * -1f == -0f (negative 0f), with 0f == -0f :-)

(on Intel, VC++, and probably on any platform that uses IEEE 754-1985 floating points)

Example on ideone (that uses GCC on some Intel compatible platform probably)

anatolyg
  • 26,506
  • 9
  • 60
  • 134
xanatos
  • 109,618
  • 12
  • 197
  • 280
  • 5
    Yes, this is guaranteed on any system that conforms to IEEE-754 (but to be perfectly clear: –0 is still "zero"). – Stephen Canon May 14 '15 at 16:33
  • 2
    @StephenCanon It is still `"0"` in the sense that `0f == -0f`, but for example if you multiply `-0f * INFINITY` and print the result, you obtain `-NaN`, so it is still `0` but its sign can be used/extracted. http://ideone.com/L6MQlQ – xanatos May 14 '15 at 16:57
  • 2
    The signbit of a NaN has no meaning, so there's actually no such thing as `–NaN`, nor is `–0 * inf` guaranteed to produce "`–NaN`" (it could produce any quiet NaN value). The signbit of `–0` can be extracted by other means, however. – Stephen Canon May 14 '15 at 17:29
  • 1
    @StephenCanon Exactly for this reason I wrote `**and print the result**, you obtain"`, the printed result of that operation on GCC on Intel is... :-) – xanatos May 14 '15 at 17:31
  • 1
    You can determine the sign of `0` by inverting it: `1./0.` => `Infinity` and `1./-0.` => `-Infinity`. Also beware of the `f` number suffix: it specifies `float` values, not `double`. – chqrlie May 14 '15 at 20:22
  • 1
    @chqrlie [Various ways to differentiate -0.0 and +0.0](http://stackoverflow.com/questions/25332133/what-operations-and-functions-on-0-0-and-0-0-give-different-arithmetic-results) – chux - Reinstate Monica May 14 '15 at 21:23
4

In addition to @xanatos fine answer, consider some of OP's middle-of-the-post concerns:

I'm wondering if there are certain situations where the (rounding) error does not apply

Candidates include some_double_y = some_double_x * 1.0 and some_double_y = some_double_x + 0.0 may never incur a rounding error.

Yet even those are suspect due to a compiler may evaluate double at higher precision considering the FLT_EVAL_METHOD == 2 where "evaluate all operations and constants to the range and precision of the long double type." In that case, an intermediate some_double_x may exist as a long double differing from an apparent double value of 0.0 or 1.0.

Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • I'm not sure I'm following "an intermediate some_double_x may exist as a long double differing from an apparent double value of 0.0 or 1.0". If some_double_x is a double variable, I understand this means it could be cast to a long double, added zero / multiplied by one (which should be no-op, right?), and then cast back to double. Are you saying that casting to higher precision and back could cause rounding errors? – Jaan Jul 12 '17 at 17:04
  • @Jaan It is not a _casting_ nor _rounding_ issue. With `double x = some_small_double(); if (x / 1.0e300) ...` may or may not take the `if()` path. The `x / 1.0e300` calculated using `double` math is certainly +/-0.0. `x / 1.0e300` calculated using `long double` math (even though the operands are both `double`) could be a non-zero number. – chux - Reinstate Monica Jul 12 '17 at 17:18
  • @Jaan "added zero / multiplied by one (which should be no-op, right?)" --> Not always. `-0.0` differs from adding zero. `-0.0 + 0.0` usually has a sum of `+0.0`. [Sometimes](https://stackoverflow.com/q/25332133/2410359) that difference is important. I _think_ `*1` is usually a no-op, but if a no-op, why code it? – chux - Reinstate Monica Jul 12 '17 at 17:25
  • OK, thanks for clarifying. I used "casting" for the converting of the floating-point number to another floating-point type, although in these cases it is not required by the language, I don't know what the correct term is. Your post seems to say that some_double_y = some_double_x * 1.0 and some_double_y = some_double_x + 0.0 are sometimes not no-ops because of the compiler evaluating double at higher precision and I wondered how that can be. But now I understand that that's actually not the case. – Jaan Jul 14 '17 at 17:29