4

I have a snippet of code that compute the sum of two squared floats:

float a, b, c;
// assign some random float to b and c
a = b*b+c*c;

Can a, the sum of the two squared floats, be negative?

The original snippet is inside a function, so a different way to put the question is the following:

bool fun(float b, float c)
{
   return b*b+c*c<0;
}

Is there any pair of values for b and c that gives fun(b,c)==true?

Alessandro Jacopson
  • 18,047
  • 15
  • 98
  • 153
  • 1
    Can they be [`std::complex`](https://en.cppreference.com/w/cpp/numeric/complex)? – Eljay Jan 19 '22 at 16:59
  • 3
    Is negative 0 count? – Jarod42 Jan 19 '22 at 16:59
  • 5
    `a >= 0` could also be `false` if any of the operands are `NaN`. – François Andrieux Jan 19 '22 at 17:00
  • @Eljay no they can't. – Alessandro Jacopson Jan 19 '22 at 17:01
  • 2
    @AlessandroJacopson **NO** – Jason Jan 19 '22 at 17:02
  • 2
    As far as I am aware, no: Signs are multiplied independently so you get positive products anyway, which won't be changed by summing up. If the result doesn't fit into a float, you should then get positive infinity – not considering the NaN case! – Aconcagua Jan 19 '22 at 17:03
  • @Jarod42 I am afraid I am not aware of negative zero :-( – Alessandro Jacopson Jan 19 '22 at 17:06
  • 1
    If you write `b*b+c*c < 0` this always be `false`, but if you will write `b*b+c*c >= 0` this can be `false` even if mathematically it can't. It can happen if one of values is `NaN` and `NaN` compared to anything in any way is always `false`. – Marek R Jan 19 '22 at 17:09
  • 2
    Note: C++ does not *require* IEEE 754 behavior for `float` and `double`. For many years, all my platforms have that behavior. However... there may be modern platforms that do not use IEEE 754 rules, and certainly older platforms that did not abide by the IEEE 754 behavior. For those platforms... you'll have to RTFM (read the fascinating manual). – Eljay Jan 19 '22 at 17:11
  • NaN case: https://godbolt.org/z/j8d4a3jrP so define condition "negative" first. – Marek R Jan 19 '22 at 17:15
  • You need to give your variables initial values, otherwise the random bit patterns could mean anything internally including a corrupt non-number with weird behaviour. – Galik Jan 19 '22 at 17:25
  • @Galik I phrased the question in a different way. – Alessandro Jacopson Jan 19 '22 at 17:58
  • 4
    unless gcc is broken the answer is No https://godbolt.org/z/adxvTr655 ;) – 463035818_is_not_an_ai Jan 19 '22 at 19:15
  • @463035818_is_not_a_number Nice! I never remember the trick to ask the compiler! – Alessandro Jacopson Jan 19 '22 at 20:11
  • 3
    @463035818_is_not_a_number: That demonstration only applies to the C implementation that GCC implements in that compilation. E.g., such an example does not show that its result holds in any C implementation, just in the one that GCC is compiling for, which likely includes some conformance to IEEE-754 et cetera. – Eric Postpischil Jan 20 '22 at 01:37
  • @EricPostpischil right, the quesiton is not whether a standard conforming implementation must return `true` for some input, but whether returning `true` for some input is conforming. – 463035818_is_not_an_ai Jan 20 '22 at 07:38

1 Answers1

7

It's not possible under IEEE754, as there is no wrap-around behaviour defined for float or double.

Let's assume that you are defining a to be negative if a < 0.0 is true. That conveniently allows us to neglect NaN cases, assuming we continue to confine the analysis to IEEE754.

Under the above assumptions it's therefore not possible for the sum of two squares to be negative. Even if a is -0.0 then a * a must be 0.0. Furthermore, if a is -inf then a * a must be +inf (mathematicians are comfortable with that as the square of a countable infinity is also countable). The sum of two squares will be no less than either of the two squares comprising the sum.


However, note that formally the behaviour of floating point overflow is undefined by the C++ standard. We're fortunate that IEEE754 is ubiquitous and overflow is defined. It's possible that an implementation has a floating point scheme which does implement some sort of wraparound to negative.

To be on the safe side, test

std::numeric_limits<float>::is_iec559
Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 1
    Did you make a typo. "Positive" instead of "Negative"? – Jason Jan 19 '22 at 17:10
  • 1
    @AnoopRana: Let's publish jointly! – Bathsheba Jan 19 '22 at 17:11
  • @FrançoisAndrieux: Formally, the behavior is undefined, so yes wraparound *is* possible. – Bathsheba Jan 19 '22 at 17:17
  • @AlessandroJacopson: Yes I just saw that. Blame my DasKeyboard which has blank keys ;-) – Bathsheba Jan 19 '22 at 17:25
  • 1
    "That conveniently allows us to neglect NaN cases." --> Setting aside IEEE754, which a compliant C implementation does not need to follow (`__STDC_IEC_559_COMPLEX__` may be not defined), I find no C spec support that specifies the result when an operand to `<` is NAN. In that case, `fun(NAN, x)` may return true. – chux - Reinstate Monica Jan 20 '22 at 14:24
  • @chux-ReinstateMonica: Neither do I. Perhaps it's not clear that the second paragraph applies under IEEE754 but not necessarily under other schemes. – Bathsheba Jan 20 '22 at 14:28
  • 1
    Is the 2nd paragraph "Let's assume ..." or "However, note ..."? IAC, I read about overflow in this answer, but not much about NAN without IEEE754 compliance. – chux - Reinstate Monica Jan 20 '22 at 14:31
  • @chux-ReinstateMonica: Well there's no harm in lobbing in a few more words. Thank you for the tip. – Bathsheba Jan 20 '22 at 14:34
  • Still, better to be explicit about what is possible w/o IEEE754 compliance too as OP did not oblige that. UV anyways. – chux - Reinstate Monica Jan 20 '22 at 14:36