Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
SELECT CASE Irregularity
#1
Note that I titled this a SELECT CASE Irregularity.  That's not exactly the case here, as all I'm doing is highlighting something that has apparently been a part of SELECT CASE for the last 30 years or more.

Keep in mind:
1) Nothing has changed.
2) Nothing is broken.
3) We won't be changing this behavior as it's the EXACT behavior QB45 produces and it's our holy grail of compatibility for all these old commands.

That said, everyone should give this next little code snippet a quick run and see the wild results for themselves before I go on to explain what's happening here:

Code: (Select All)
Dim i As Integer
For x = 0 To 2 Step .1
    i = x
    Print x, i,
    Select Case i
        Case Is < x: Print "Round Down",
        Case Is = x: Print "Equal",
        Case Is > x: Print "Round up",
    End Select
    Select Case x
        Case Is > i: Print "Round Down"
        Case Is = i: Print "Equal"
        Case Is < i: Print "Round up"
    End Select
Next



Now, did you run that?

If not, run that before you continue reading.  Go on.  It'll take all of 30 seconds to copy/paste and run.  See if any of you guys can sort out what's going on here, and see if these are the results you were expecting.







Okies, I'm going to assume you guys tried the above at this point.

ISN'T THE RESULT THERE COMPLETELY MIND BOGGLING??!!

i = x, but x <> i

Now.... how the BLEEP does that make even the slightest bit of sense???

.
.
.
Any clue?
.
.
.
.

Apparently, when dealing with SELECT CASE, the comparison type is cast to match the case type!!

Again, keep in mind that this isn't new behavior; it's the exact same thing that we've seen for the past thirty years.  But... WHO KNEW??!!



What's going on here is basically:

SELECT CASE i    <--- i is an INTEGER
   CASE IS < x     <--- here, x is a float so its value is cast to an INTEGER for compare.  It's basically the same as CINT(x).  A float value of 1.1 ends up being processed as if it was simply 1.

And that conversion from float to integer with X means that the values are always going to match perfectly.

.
.
.

And with the second part?

We see the same thing happening:

SELECT CASE x    <--- here, x is a SINGLE
    CASE is > i      <--- here, i is an INTEGER, so we cast it to a FLOAT.   Of course an integer value of 1 is also the exact same float value of 1.  We're not changing the value here of anything, so we're comparing the full value of x to i, without any rounding occurring.



Wild.  Right?

Just keep in mind, this is the way it's always been.  You've been coding and having this happen for years and years, and either didn't notice, or weren't affected by it in any sort of meaningful way.

But it *IS* something to keep in mind moving forward, to make certain that you're getting the results and comparisons which you want.  I'd stumbled across this while playing around and testing things with the CINT, CLNG, _ROUND topic, and it blew my mind that I'd never ever noticed this strange little quirk before.

It's always been here.  Always been doing things this way.   But I certainly didn't know about it, and I'm willing to be a vast majority of our user base didn't know either.

SELECT CASE casts the CASE type to match the SELECT CASE type. 

Be aware of that moving forward guys.  It may save you some serious head scratching and debugging sometime in the future.  Wink
Reply
#2
interesting Steve
a tiny change on your snippet for better output
Code: (Select All)

$Console:Only
_Dest _Console

Dim i As Integer
'Dim As Single x

For x = 0 To 2 Step .1
    i = x
    Print Using "##.##  "; x, i,
    Select Case i
        Case Is < x: Print "Round Down",
        Case Is = x: Print "Equal",
        Case Is > x: Print "Round up",
    End Select
    Select Case x
        Case Is > i: Print "Round Down"
        Case Is = i: Print "Equal"
        Case Is < i: Print "Round up"
    End Select
Next

I get
Code: (Select All)

0.00  0.00  Equal          Equal
0.10  0.00  Equal          Round Down
0.20  0.00  Equal          Round Down
0.30  0.00  Equal          Round Down
0.40  0.00  Equal          Round Down
0.50  0.00  Equal          Round Down
0.60  1.00  Equal          Round up
0.70  1.00  Equal          Round up
0.80  1.00  Equal          Round up
0.90  1.00  Equal          Round up
1.00  1.00  Equal          Round Down
1.10  1.00  Equal          Round Down
1.20  1.00  Equal          Round Down
1.30  1.00  Equal          Round Down
1.40  1.00  Equal          Round Down
1.50  2.00  Equal          Round up
1.60  2.00  Equal          Round up
1.70  2.00  Equal          Round up
1.80  2.00  Equal          Round up
1.90  2.00  Equal          Round up

in FreeBasic I get
Code: (Select All)

0            0            Equal        Equal
0.1          0            Round Down    Round Down
0.2          0            Round Down    Round Down
0.3          0            Round Down    Round Down
0.4          0            Round Down    Round Down
0.5          0            Round Down    Round Down
0.6          1            Round up      Round up
0.7          1            Round up      Round up
0.8000001    1            Round up      Round up
0.9000001    1            Round up      Round up
1            1            Round Down    Round Down
1.1          1            Round Down    Round Down
1.2          1            Round Down    Round Down
1.3          1            Round Down    Round Down
1.4          1            Round Down    Round Down
1.5          2            Round up      Round up
1.6          2            Round up      Round up
1.7          2            Round up      Round up
1.8          2            Round up      Round up
1.9          2            Round up      Round up
Reply
#3
@Jack was the FreeBASIC one compiled with the -lang qb ? Just curious.
Reply
#4
a740g
no it was not, but I just did and the answer is the same
I think that it's good to know the differences in case somebody wants to port code from one to the other
Reply
#5
Just a note: As strange as I find this, this is 100% the same as how QB45 handles it.

Honestly, this is a case which I personally consider BUGWARD COMPATIBLE.
Reply
#6
(05-05-2025, 08:59 PM)SMcNeill Wrote: Just a note: As strange as I find this, this is 100% the same as how QB45 handles it.

Honestly, this is a case which I personally consider BUGWARD COMPATIBLE.

"Bugward" is not a word I'm familiar with; it's not in my dictionary - but I think it's a great candidate for the next edition!
I like it !  Big Grin
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, Western Australia.) Big Grin
Please visit my Website at: http://oldendayskids.blogspot.com/
Reply
#7
Hi
interesting behaviour, I think of this is a copy of CINT issue (also that hidden into INT keyword)

I run your demo but for my weakness I need to add the name at the column of data showed.
[Image: immagine-2025-05-09-225828179.png]

we can observe that i as INTEGER variable takes the value of X that is a single variable. 
So I expect that i takes the unity loosing the digits after the point . as we can get with i=fix(x), instead x has been transformed into integer like i = cint(X) and for this reason it works following the financial math rule for rounding.

(I think to know WHY financial rounding works in this manner, the first rounding is down the second is up and again this cycle for infinite times.
Talking about money to give or to take, in the first turn the excess of money has been taken, in the second turn it has been given. The bank always wins! Before take and after give Wink )

What do I find weird in this output?

1. 
the output of .8 and .9  in the X column. (.8000001 and .9000001) ????

2. 
the 11th row  in which   X = 1 (I assume 1.00)  and i = 1 so  i vs x gives EQUAL (1 = 1.00) instead  x vs i gives Rounded down (1.00 vs 1), while at the first row X = 0 (I assume 0.00) and i = 0 so i vs x gives EQUAL and x vs i gives EQUAL

3.
i vs x gives always EQUAL

the BUGWARD compatibility is the price to pay

As showed by Jack also Freebasic uses the same BUGWARD rule.
Reply




Users browsing this thread: 1 Guest(s)