Large UInt32 is less than 0?

3521340885 is less than 0? Is this by design etc? Do I need to always cast 0 (zero) to UInt32 before comparisons?

I mean, shouldn’t the compiler assume an UInt32 “zero” instead of Integer “zero” since the first item in the comparison is an UInt32?

  Dim result As Boolean = False
  Dim number1 As UInt32
  Dim aVariant As Variant
  
  aVariant = 3521340885 // Larger than Int32 but within UInt32 range.
  
  If aVariant >= 0 Then
    result = True
    
  Else
    result = False
    
  End If
  
  // result = False at this point.
  
  number1 = aVariant.UInt32Value
  
  If number1 >= 0 Then
    result = True
    
  Else
    result = False
    
  End If
  
  // result = False at this point.
  
  number1 = 3521340885 // This time we enter the number directly.
  
  If number1 >= 0 Then
    result = True
    
  Else
    result = False
    
  End If
  
  // result = False at this point.
  
  If number1 >= UInt32(0) Then
    result = True
    
  Else
    result = False
    
  End If
  
  // result = True at this point.

I think I found the answer. Somewhere in the forum it’s explained that the max common type between both is used which in this case is Int32 which gives the less than zero result…

Well, it sounds “wrong” (for me) but one can hardly believe xojo can (or should) change this. Casting in advance doesn’t hurt, I suppose.

Hello Yosef,

If the number that is being used is out-of-range (also called overflow) then the value wraps itself around to a negative value. There is helpful information at Integer Datatypes .

Here is some example code that I borrowed from your example to help explain wrapping.

[code] Dim result as Boolean
Dim aVariant As Variant

aVariant = 3521340885 // Larger than Int32 but within UInt32 range.

If aVariant >= 0 Then
result = True

Else
result = False

End If
MsgBox CStr(aVariant.Int32Value)
MsgBox CStr(aVariant.Int64Value)
[/code]

Xojo does not know what value a variant is supposed to be and by adding the datatype after the variant variable then the number works with the rules of Xojo.

An Int32Value has a range of -2,147,483,648 to -2,147,483,647, which is outside of the range of the example number:3,521,340,885. With this number out-of-range then the number wraps from a positive to a negative number.

When the Int64Value is used (-9,223,372,036,854,775,808 to +9,223,372,036,854,775,807), then this fits in the range and the correct number is displayed.

It is important to choose the data type which works with the numbers that are expected in the program. :slight_smile:

Eugene’s answer is the correct one, not yours.

An additional remark: one would think that the new Auto datatype would throw a TypeMismatchException in this case, but unfortunately it doesn’t (for Int8 to Int64 and from UInt8 to UInt64).

Not really, 3521340885 is within the range of an UInt32, the data type used in my code.

AFAIK a Variant without specifying what it holds will return an Integer (= Int32) no matter what the target variable is – there is no coercion taking place:

Dim x As UInt32 = aVariant // Variant will return a Int32 Dim x As UInt32 = aVariant.UInt32Value // Variant will return an UInt32

0 is a signed 32-bit integer by default, so comparing to 0 involves an implicit conversion. UInt32(0) works as expected since there is no conversion.

The compiler can warn you about these conversions but it doesn’t by default. From the Project menu select “Analysis Warnings” (in Realstudio it’s “Warnings…”) and put a check mark next to “converting from item1 to item2 causes the sign information to be lost, which can lead to unexpected results.”

Andrew, I agree with you and I’ve already cast all “numbers” that must be compared to UInt32s etc.

Eli:

  
  Dim result As Boolean = False
  Dim number1 As UInt32
  Dim number2 As UInt32
  Dim aVariant As Variant
   
  aVariant = 3123456789
  
  number1 = aVariant
  number2 = aVariant.UInt32Value
  
  If number1 <> number2 Then result = True
  
  If number1 >= 0 Then result = True
  
  If number2 >= 0 Then result = True
  
  // result is still false.
  
  // and, more importantly:
  
  number1 = 3123456789
  
  If number1 > 0 Then result = True
  
  // result is still false.

No, you don’t:

aVariant = 3123456789

May I suggest you follow the values in the debugger?

Indeed, there seems to be a bug when using comparison function with UInt32:

Dim n As UInt32 = 3123456789 MsgBox Str(n >= 0) // shows False

Dim n As UInt32 = 2147483647 // largest Int32 works, add 1 and ... Dim n As UInt32 = 2147483648 // ... it does not work (for all UInt32 up to the maximum value it can hold)

Markus: already did, they show correctly, as expected.

Eli: As I said in my second post (the accepted answer) someone from Xojo already explained This

Morality : variants bite :wink: Norman told.

I agree but JSONItems store variants, that’s how I came across this issue. :slight_smile:

Why not pass aVariant a formatted string containing the value, and convert it back to a Uint32 when needed ?

well, that’s very slow… :slight_smile:

I will try to change the variant’s behaviour with Operator_Compare . Not sure it’s possible or a good thing though…

The UInt32(0) approach doesn’t hurt

Have you tried using Auto with ParseJSON/GenerateJSON instead of Variant with JSONItem?

And, of course sign on to this feature request:

<https://xojo.com/issue/4920>