Comparisons with Unsigned Integers

Seems like today was the day for me to have problems involving unsigned integers. For instance, look at the code below:

[code] Dim t As Text
Dim ui64 As UInt64 = &hFFFFFFFFFFFFFFFF
If ui64 > 0 Then // ui64 is not greater than zero
t = " ui64 > 0"
Else
t = " ui64 is not > 0"
End If

// this code works
ui64 = &hFFFFFFFFFFFFFFFF
If ui64 > &h0 Then // ui64 is greater than zero
t = " ui64 > 0"
Else
t = " ui64 is not > 0"
End If
Break[/code]

If you have an unsigned integer that has the most significant bit set it will fail with a compare with “0”. Can’t really call the msb a sign bit since it is unsigned. If you compare with “&h0”, it works as expected as it seems to force an unsigned comparison. Is this the expected behavior? At first I thought that the compiler would convert to the type of the variable and then compare but that is not what’s happening. It appears that it is converting to the type of the literal (double maybe?) and then comparing ,and since the msb is set it is comparing a negative value with zero. Whatever the compiler is doing it is confusing to say the least.

Is it possible to specify an unsigned literal without using &h?

not sure… but I’ll bet its is casting you UInt back to Int in order to compare it to Int(0)
where when you say &H0 it does a binary compare without casting…

just a guess …

It is just not in the way you think it does it
The compiler figures out a common type between the operands (uint64 and 0)

If ui64 > 0 Then // ui64 = Uint 0 = integer … common type between them is INTEGER

Try

If ui64 > Ctype(0,Uint64) Then // this forces the comparison between two Unit64’s
or
dim uint64Zero as Uint64 = 0

If ui64 > Uint64Zero Then // this compares two Unit64’s

I assume that this applies to literals surrounding other operators as well (±/*MOD …). Looks like I will be doing a top to bottom code review and enclosing integer literals with ctype() where Uint evaluations are involved. Thanks for the input.

This is something I’d like to improve, but it’s risky because it potentially breaks an unknown number of programs that rely on the current behavior.

Its not just literals
The compiler does this all over the place with variables as well - it always tries to find a common type for the comparison
Usually you don’t compare a Uint64 to an Integer but you’d get the same effect in the case you did

    dim ui64 As UInt64 = &hFFFFFFFFFFFFFFFF
    dim i as integer = 0

    if iu64 > i then // compiler still figures out a common type here

at least the compiler for XOJO will autocast in some cases … try SWIFT, you need to cast ANY thing that isn’t the same type
Float, CGFloat, Double are not “the same”
Int, Int64 are NOT the same etc…

I did try Swift in fact. I converted a small portion of my big integer library to Swift and the strong typing did indeed drive me nuts!

Last week I submitted a small article to xDev about exactly this issue … :slight_smile:

[quote=207640:@Norman Palardy]It is just not in the way you think it does it
The compiler figures out a common type between the operands (uint64 and 0)

If ui64 > 0 Then // ui64 = Uint 0 = integer … common type between them is INTEGER [/quote]

Actually that is not quite the case here as far as I understand it …

For example look at this:

[code]Dim n2 As UInt32 = 3123456789
MsgBox Str(n2 >= 0)

Dim n3 As UInt64 = 3123456789
MsgBox Str(n3 >= 0)[/code]

If the problem would be a common type of integer then both would result in FALSE … but that isn’t the case!

Solution in the forthcoming xDev (if Mark accepts it) but if you can’t wait send me a PM and I’ll tell you :wink:

[quote=207712:@Markus Winter]Dim n2 As UInt32 = 3123456789
MsgBox Str(n2 >= 0)[/quote]
n2 is treated as Int32 (as is 0).

[quote]Dim n3 As UInt64 = 3123456789
MsgBox Str(n3 >= 0)[/quote]
n3 is treated as Int64 (as is 0).

@Eli Ott: Yup. Because the common type between UNSIGNED and SIGNED is SIGNED. So you’ll get a conversion to SIGNED before the comparison. So (as with n2) in the original question this conversion to SIGNED results in an integer overflow error.

<https://xojo.com/issue/3726>
This feedbackreport is dated 5. august 2008 and the bug still exists in the latest Xojo version.
I thought that the new framework was a good moment for implementing a more solid handling of overflow/underflow for all integer types.
Besides that, the compiler should for literals allways choose a type where the value of the literal fits in. If the literal is larger than the largest type supported by Xojo (currently (u)int64), then an exception should be raised or if there is no other way at least a conversion to double should take place.

Not sure I’d all it a “bug”
Thats a language design issue that if we changed it could, as Joe previously noted, break an untold number of applications that rely on the current behavior

I.M.H.O., not implementing an improved handling of over-/underflow of integers turns many (existing and newly created) programs in a “casino experiance” or a feeling of Russian Roulette.