Hi, I'm having trouble with long integers in the -lang qb dialect, which are available with __LONGINT. They don't seem to accept much more than 53 bits (around ±2^52), instead of the claimed 64 bits (±2^63). Perhaps this is an old solved topic, I'm sorry, I haven't found it. See the next program in the -lang qb dialect; it doesn't matter if we use the long integer suffix LL after the numbers (e.g. 52LL) or not, the output is always the same: RIGHT followed by WRONG:
DIM AS __LONGINT X,Y
X=2^52
Y=2^52+1
IF X<>Y THEN PRINT "RIGHT" ELSE PRINT "WRONG"
X=2^53
Y=2^53+1
IF X<>Y THEN PRINT "RIGHT" ELSE PRINT "WRONG"
SLEEP: END
Do we have a bug?
Trouble with long integers.
Re: Trouble with long integers.
This behavior is normal and is due to the precision of the conversion: Double -> LongInt, because the Operator ^ returns a Double.
A Double contains at most 53 bits of precision, or about 15 decimal digits.
Works for example with:
X=2^53
Y=2^53+2
Otherwise:
A Double contains at most 53 bits of precision, or about 15 decimal digits.
Works for example with:
X=2^53
Y=2^53+2
Otherwise:
Code: Select all
#lang "qb"
DIM AS __LONGINT X,Y
X=2^53
Y=2^53+1
PRINT X
PRINT Y
IF X<>Y THEN PRINT "RIGHT" ELSE PRINT "WRONG"
PRINT
X=&h20000000000000 '' 2^53
Y=&h20000000000000+1 '' 2^53+1
PRINT X
PRINT Y
IF X<>Y THEN PRINT "RIGHT" ELSE PRINT "WRONG"
SLEEP
Re: Trouble with long integers.
The crt pow function seems a bit more accurate.
Code: Select all
#lang "qb"
declare function pow cdecl alias "pow"(byval as double,byval as double) as double
DIM AS __LONGINT X,Y
X=pow(2,52)
Y=pow(2,52+1)
IF X<>Y THEN PRINT "RIGHT" ELSE PRINT "WRONG"
X=pow(2,53)
Y=pow(2,53+1)
IF X<>Y THEN PRINT "RIGHT" ELSE PRINT "WRONG"
SLEEP: END
Re: Trouble with long integers.
Rather 'pow(2,52)+1' and 'pow(2,53)+1', but it still works !
Re: Trouble with long integers.
Works also if returning the exponentiation from a freeBASIC function:
Also works:
X=2^53
Y=__CAST(__LONGINT,2^53)+1
It all depends on how the Double -> LongInt conversion is done.
Code: Select all
#lang "qb"
function power(byref a as double,byref b as double) as double
power=a^b
end function
DIM AS __LONGINT X,Y
X=power(2,52)
Y=power(2,52)+1
Print X
Print Y
IF X<>Y THEN PRINT "RIGHT" ELSE PRINT "WRONG"
X=power(2,53)
Y=power(2,53)+1
Print X
Print Y
IF X<>Y THEN PRINT "RIGHT" ELSE PRINT "WRONG"
SLEEP
X=2^53
Y=__CAST(__LONGINT,2^53)+1
It all depends on how the Double -> LongInt conversion is done.
Re: Trouble with long integers.
Use shift left:
1ll is needed (in case of 32 bit fbc) to tell the compiler to store 1 as a longint, see: Literal Suffix in Standard Data Type Limits
To further clarify the problem, see compiler output of:
Which should give for 32 bit fbc:
Code: Select all
dim as longint X, Y
X = 1ll shl 52 '2^52
Y = 1ll shl 52 + 1 '2^52+1
if X<>Y then print "RIGHT" else print "WRONG"
print Y-X
X = 1ll shl 53 '2^53
Y = 1ll shl 53 + 1 '2^53+1
if X<>Y then print "RIGHT" else print "WRONG"
print Y-X
sleep: end
1ll is needed (in case of 32 bit fbc) to tell the compiler to store 1 as a longint, see: Literal Suffix in Standard Data Type Limits
To further clarify the problem, see compiler output of:
Code: Select all
#print typeof(2 ^ 52)
#print typeof(1ll shl 52)
Code: Select all
DOUBLE
LONGINT
Re: Trouble with long integers.
I appreciate all the answers, thanks.
In regard to the answers that use the function POW or POWER, in my platform or version of FreeBasic it just works POWER (not POW), provided that in the POWER definition I substitute __LONGINT for DOUBLE; so for me it works correctly:
#lang "qb"
FUNCTION POWER(BYREF A AS __LONGINT,BYREF B AS __LONGINT) AS __LONGINT
POWER=A^B
END FUNCTION
DIM AS __LONGINT X,Y
X=POWER(2,52)
Y=POWER(2,52)+1
PRINT X
PRINT Y
IF X<>Y THEN PRINT "RIGHT" ELSE PRINT "WRONG"
X=POWER(2,53)
Y=POWER(2,53)+1
PRINT X
PRINT Y
IF X<>Y THEN PRINT "RIGHT" ELSE PRINT "WRONG"
SLEEP: END
In regard to the answers that use the function POW or POWER, in my platform or version of FreeBasic it just works POWER (not POW), provided that in the POWER definition I substitute __LONGINT for DOUBLE; so for me it works correctly:
#lang "qb"
FUNCTION POWER(BYREF A AS __LONGINT,BYREF B AS __LONGINT) AS __LONGINT
POWER=A^B
END FUNCTION
DIM AS __LONGINT X,Y
X=POWER(2,52)
Y=POWER(2,52)+1
PRINT X
PRINT Y
IF X<>Y THEN PRINT "RIGHT" ELSE PRINT "WRONG"
X=POWER(2,53)
Y=POWER(2,53)+1
PRINT X
PRINT Y
IF X<>Y THEN PRINT "RIGHT" ELSE PRINT "WRONG"
SLEEP: END