4

As shown in the image, it is throwing the error. Please help me to find the solution.

Here I am using floating numbers in the switch, which is supposed to print 10.
What is the reason for this error? and why?

switch case example screehshot

#include <stdio.h>
void main() {
 float a = 1.0;

 switch (a) {
    case 1:
     printf ("1");
     break;

    case 1.0:
     printf ("10");
     break;
    }
}
  • 6
    1. Because the language definition says so. 2. Because comparing floating-point numbers for exact equality (which a `switch` statement implicitly does) is often a bad idea. 3. Because using floating-point variables as control variables is usually a bad idea. – Steve Summit Nov 10 '21 at 11:33
  • If you have a specific example of a piece of code you want to write which has a `switch` statement on a floating-point value, you might want to ask about that. There's a small chance the answer will be, "Yeah, that would work, too bad you can't use `switch`, you'll have to use an `if`/`else` chain instead." But there's a much larger chance we'll be able to suggest a better way to write it. – Steve Summit Nov 10 '21 at 11:37
  • 1
    @SteveSummit, this is true for fractional numbers, but small integers (up ~1e6) are perfectly represented by `float` and they can safely used in comparisons – tstanisl Nov 10 '21 at 11:52
  • @tstanisl Indeed, and that's why I said "often" instead of "always". – Steve Summit Nov 10 '21 at 11:54
  • 1
    The C standard says: "The controlling expression of a switch statement shall have **integer type**" – Support Ukraine Nov 10 '21 at 12:40
  • @tstanisl All `float` finite value are exact and can be used in a comparison as well as any other. Small integers (up ~1e6) are not special. As with integer type, FP types cannot represent every math/source code value. `float` can represent about 2^32 values exactly. – chux - Reinstate Monica Nov 11 '21 at 06:37
  • `switch ((int)(angle * 1000000)) { case 785398: puts("right angle (approximate)"); break; }` – pmg Dec 07 '21 at 10:09
  • Rule of thumb: when in doubt, don't use floats. – chqrlie Feb 14 '22 at 11:57
  • @tstanisl And, of course, there are certain fractional numbers that can safely be compared for exact equality also: 0.5, 0.25, 0.125, 0.265625, etc. – Steve Summit Feb 14 '22 at 13:17
  • it would also help if you showed some code. Its perfectly possible that your issue has nothing to do with floats or switch statements, we are only guessing here – pm100 Feb 16 '22 at 05:51
  • @SteveSummit, I modified that question because stack over flow blocked me from asking questions, so to get it back, I was supposed to modify my question grammatically as they mentioned. And there is no wonder. Your answer helped me thank you. – Mahantesh. N. Hadimani. Jul 18 '22 at 04:40

3 Answers3

5

Because switch depends on exact, plain-data comparison.

Comparisons between floats probably don't work as you expect them to, for example, there's a negative and a positive zero.

See: Is floating point math broken?

For these reasons, you can't "simply" say "a == b" when you mean that, as a human. That's why the C standard simply doesn't allow it as a case in a switch.

Truth is: the fact that you're trying to do that is a good reason for forbidding it! Either you're using floats where you shouldn't (namely, to store a limited set of discrete values), or you haven't really understood how floats work, and using them in a switch statement will lead to unexpected behaviour.

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
  • 2
    But you *can* say `a == b`! – Steve Summit Nov 10 '21 at 11:38
  • 2
    @SteveSummit True, but more often than not the result of such comparisons for floating point numbers will not be what's expected. – Some programmer dude Nov 10 '21 at 11:39
  • 1
    you *can* say that, but it's not "simple", or "the correct result from a human point of view", that's why I used *you can't "simply" say… when you mean that, as a human*, @SteveSummit – Marcus Müller Nov 10 '21 at 11:39
  • 3
    My complaint was that the answer seemed to say that the language forbade using `==` on floating-point values. It's better now. – Steve Summit Nov 10 '21 at 11:43
  • @SteveSummit yep, better now thanks to your feedback, so thank you! – Marcus Müller Nov 10 '21 at 11:43
  • 4
    One other little nit: your `3./5. != 0.6` example is excellent, or would be, except that it's false! On my computer, at least, `3.0f/5.0f` is in fact exactly the same as `0.6f` (although neither is equal to the rational number 3/5). The simple example that surprisingly fails is `0.1f + 0.2f`, which does not equal `0.3`, although it does equal `0.3f`. And then `0.1 + 0.2` does not equal `0.3`. Fun, fun. – Steve Summit Nov 10 '21 at 11:52
  • 1
    "Because switch depends on exact, plain-data comparison." --> Hmmm, all `float` finite values are exact - so a weak rational. C _could_ have allowed `switch(some_double)`, it is simple not that good an idea for [various reasons](https://stackoverflow.com/questions/69912533/why-cant-we-use-floating-point-numbers-in-switch-conditional-statements#comment123583634_69912533). Exactness of a `float` is not the issue. Compares works as expected, it is `+,-,*,/,...` that does not "work" as grade school math. – chux - Reinstate Monica Nov 11 '21 at 06:43
  • 1
    Using math operators to show that a type is not qualified in a compare would fail `int` too as `7/5 == 4/3` is true. It is that math operators for integer and FP differ in some regards than school math. – chux - Reinstate Monica Nov 11 '21 at 06:52
  • @chux-ReinstateMonica let's not get into the semantics of what "are exact" would mean, as that's not even sufficient – they all need to be *unambiguous* (which IEEE754 floats aren't, there's more than one way to represent the same finite number, and for other float formats: depends. Do you want to base a language construct on some vendor-specific FPU implementation?). Also, not my rationale, but that of people designing the C language some 50 years ago (and 1999, again). – Marcus Müller Nov 11 '21 at 10:27
  • 1
    IEEE754 floats are unambiguous. With binary FP, there is only one expectation to "more than one way to represent the same finite number", 0.0 and -0.0 having the same value. All other `float` have different values. "Do you want to base a language construct on some vendor-specific FPU implementation?" --> that is what started C and was successful: the incorporating of various vendor standards - many compromises. Even IEEE754 remains with options in niched areas to cope with vendor specific FPU implementation. – chux - Reinstate Monica Nov 11 '21 at 18:49
  • @chux-ReinstateMonica that is factually inaccurate. IEEE754 simply has more than one representation for many numbers, not only for exactly +-0; in fact, there's 2²⁵-2 denormalized numbers. – Marcus Müller Nov 11 '21 at 19:52
  • Please provide the encoding of 2 `float` that have the same value, aside from 0. – chux - Reinstate Monica Nov 11 '21 at 21:02
  • wouldn't the largest denormalized and the smallest normalized number be the same? – Marcus Müller Nov 11 '21 at 21:32
  • 2
    @MarcusMüller IEEE-754 *decimal* floats have ambiguities, but the binary ones do not, except for ±0. The smallest normal `float` is `0x00800000` or 0b1.0 × 2^(-126) or 1.17549435e-38. The largest subnormal `float` is a little bit smaller: `0x007fffff` or 0b0.fffffe × 2^(-126) or 1.17549421e-38. – Steve Summit Feb 14 '22 at 13:13
1

As for the "Please help me" part of your question, you can probably implement that more-or-less as follows...

rather than

double x=1.,y=2.;
blah; blah; blah;
switch(x){
  default: break;
  case y: blah; break;
  }

try instead something like

double x=1., y=2., xmax=10000., xmin=1.;
int   ix=1, iy=2,  imax=100;
blah; blah; blah;
ix = ((x-xmin)/(xmax-xmin))*((double)imax);
iy = ((y-xmin)/(xmax-xmin))*((double)imax);
switch(ix){
  default: break;
  case iy: blah; break;
  }
eigengrau
  • 153
  • 7
0

why can't we use floating point numbers in switch conditional statements?

  1. Because the language definition says so.

  2. Because comparing floating-point numbers for exact equality (which a switch statement implicitly does) is often a bad idea.

  3. Because using floating-point variables as control variables is usually a bad idea. @Steve Summit

  4. No compelling need for this feature.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • this answer says exactly what mine says, more superficially, but again, so I'll take that as a compliment. – Marcus Müller Nov 11 '21 at 10:29
  • I think this answer could really be more - and a good alternative to my answer! For 2.-4., could you elaborate? You're just stating things (which I also already stated in my answer) as facts, but give no reasons. You might see different reasons than I do, but at least I put mine in my answer! – Marcus Müller Nov 11 '21 at 10:32