Search code examples
delphidelphi-7

Issue with rounding Int64 and negative numbers, what am i missing here?


Last month we had an issue with a commission payment. The dollar amount exceeded the actual value an integer could hold. This is the first time it has happened since the App was written.

clist           : tstringlist; 

clist.objects[dex]:= tobject( round((10000*DM.QryComm1.fieldbyname('COSS_NET_CHECK_AMT').asfloat)) + integer(clist.objects[dex]));

the dollar amount was $215,980.72 we multiply by 10000 and get an answer of 2159807200. the max for an integer is 2147483647.

So we increased the integer to an int64.

clist.objects[dex]:= tobject( round((10000*DM.QryComm1.fieldbyname('COSS_NET_CHECK_AMT').asfloat)) + int64(clist.objects[dex]))

The problem that we are having is if a negative integer comes through when we are using int64, a default value of 4294428496 is placed in the tstringlsit and not the actual value. This only happens with negatives. The positive numbers are fine.

We have been researching all over the web and can not find a solution.

Here is the original code.....

while not DM.QryComm1.eof do 
begin 
 . 
 . 
 {Sum net amount for each BVCICI_ID} 
 dex:=clist.indexof(BVCICI_ID); 
 if dex<> -1 then 
  clist.objects[dex]:= tobject( round((10000*DM.QryComm1.fieldbyname('COSS_NET_CHECK_AMT').asfloat)) +   
                       integer(clist.objects[dex])) 
 else 
  clist.addobject(BVCICI_ID, tobject( round(DM.QryComm1.fieldbyname('COSS_NET_CHECK_AMT').asfloat*10000)));

Solution

  • Looks like you're casting a 64 bit integer to a 32 bit pointer, which obviously loses information. It seems like your code is basically Int64(UInt32(some64BitInteger))

    As a workaround you can create a new object that contains an Int64 as field. But of course you'll need to take care of destroying it or you'll leak memory.

    A clean solution would be a string->Int64 dictionary, but those are only available in recent versions of delphi.