02-25-2024, 02:19 AM
A simple function so we can make certain that we convert a value to the type that we want it to be when doing math stuffs.
QB64 tries to assign math to the largest type that is involved in the math, and this can sometimes lead to some rather odd results.
DIM UL AS _UNSIGNED LONG
UL = -1
PRINT -1 * UL
Now, most folks would think that -1 * -1 would, of course, be 1.
It's NOT.
The reason is we're multiplying a const value of -1 (which, I think defaults to a LONG type) times an UNSIGNED LONG type, so the return value becomes and UNSIGNED LONG type for us... and who here wants to tell us what the value of -1 is, with an UNSIGNED LONG?? (Hint: It's not 1. )
So add in a simple ConvertTo command in there, make certain that the result is the type that you'd expect to get back, and you can happily do math stuffs forevermore without this type of issue biting you in the butt.
PRINT ConvertTo("Long", -1 * UL) <-- and this would print the LONG value of the result and not the UNSIGNED LONG value.
Simple enough, right?
Code: (Select All)
PRINTConvertTo("bit", -1)
PRINT ConvertTo("unsigned bit", -1)
PRINT ConvertTo("byte", -1)
PRINT ConvertTo("~ byte", -1)
PRINT ConvertTo("integer", -1)
PRINT ConvertTo("unsigned integer", -1)
PRINT ConvertTo("&", -1)
PRINT ConvertTo("~&", -1)
PRINT
PRINT "And here's why this type of stuff is needed:"
DIM UL AS _UNSIGNED LONG: UL = 1
PRINT -1 * UL, ConvertTo("&", -1 * UL), "const * unsigned long = unsigned long"
PRINT -1` * UL, ConvertTo("&", -1` * UL), "bit * unsigned long = unsigned long"
PRINT -1%% * UL, ConvertTo("&", -1%% * UL), "byte * unsigned long = unsigned long"
PRINT -1% * UL, ConvertTo("&", -1% * UL), "integer * unsigned long = unsigned long"
PRINT -1& * UL, ConvertTo("&", -1& * UL), "long * unsigned long = unsigned long"
PRINT -1&& * UL, ConvertTo("&", -1&& * UL), "integer64 * unsigned long = integer64"
FUNCTION ConvertTo## (type$, num##)
temp$ = _TRIM$(UCASE$(type$))
'check for some unsigned indicators
IF LEFT$(temp$, 1) = "~" THEN Unsigned = -1: temp$ = _TRIM$(MID$(temp$, 2))
IF LEFT$(temp$, 8) = "UNSIGNED" THEN Unsigned = -1: temp$ = _TRIM$(MID$(temp$, 9))
IF LEFT$(temp$, 1) = "U" THEN Unsigned = -1: temp$ = _TRIM$(MID$(temp$, 2))
'convert to the desired type
SELECT CASE UCASE$(temp$)
CASE "LONG", "&"
IF Unsigned THEN
temp~& = num##
ConvertTo = temp~&
ELSE
temp& = num##
ConvertTo = temp&
END IF
CASE "BIT", "`"
IF Unsigned THEN
temp~` = num##
ConvertTo = temp~`
ELSE
temp` = num##
ConvertTo = temp`
END IF
CASE "BYTE", "%%"
IF Unsigned THEN
temp~%% = num##
ConvertTo = temp~%%
ELSE
temp%% = num##
ConvertTo = temp%%
END IF
CASE "INT", "INTEGER", "%"
IF Unsigned THEN
temp~% = num##
ConvertTo = temp~%
ELSE
temp% = num##
ConvertTo = temp%
END IF
CASE "INT64", "INTEGER64", "_INTEGER64", "&&"
IF Unsigned THEN
temp~&& = num##
ConvertTo = temp~&&
ELSE
temp&& = num##
ConvertTo = temp&&
END IF
CASE "SINGLE", "!"
temp! = num##
ConvertTo = temp!
CASE "DOUBLE", "#"
temp# = num##
ConvertTo = temp#
CASE "FLOAT", "_FLOAT", "##"
temp! = num##
ConvertTo = temp!
END SELECT
END FUNCTION
QB64 tries to assign math to the largest type that is involved in the math, and this can sometimes lead to some rather odd results.
DIM UL AS _UNSIGNED LONG
UL = -1
PRINT -1 * UL
Now, most folks would think that -1 * -1 would, of course, be 1.
It's NOT.
The reason is we're multiplying a const value of -1 (which, I think defaults to a LONG type) times an UNSIGNED LONG type, so the return value becomes and UNSIGNED LONG type for us... and who here wants to tell us what the value of -1 is, with an UNSIGNED LONG?? (Hint: It's not 1. )
So add in a simple ConvertTo command in there, make certain that the result is the type that you'd expect to get back, and you can happily do math stuffs forevermore without this type of issue biting you in the butt.
PRINT ConvertTo("Long", -1 * UL) <-- and this would print the LONG value of the result and not the UNSIGNED LONG value.
Simple enough, right?