Wrong results with Integer numbers math. lazarus / 21-General ---------------------------------------------------------------------- Apollo286 · 2021-01-05 22:03 Hi, I wrote simple code an I have two different results on Win10 and Ubuntu. I don't know where is the problem. Here is my code: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i ...var a, b, c, d : longint;      myResult : Int64;...  a := 828;  b := 653;  c := 12362752;  d := 552;            myResult := ((a-b)*c) div d;   Lazarus 2.0.10, in Ubuntu:        myResult = 3919350              Lazarus 2.0.10, in Windows:     myResult = -3861387 The same code, but two different results. Result in Ubuntu is valid for me. I think - problem is with integer division, but I don't know to fix it. Please, have somebody any tip or solution for my problem? Thx. ---------------------------------------------------------------------- MarkMLl · 2021-01-05 22:15 You'd help everybody enormously if you said what version of FPC, what processor you were using, and what mode the compiler is running in. I've spent a chunk of the evening investigating the history of why the mod operator acts oddly so just don't start on that one (yet)... OK? :-) MarkMLl ---------------------------------------------------------------------- wp · 2021-01-05 22:40 Your calculation in myResult has an integer overflow. Turn on the "I/O overflow" box in the Debugging page of the Project options to get an error message. To fix the problem declare all longint as Int64 (or at least one of the factors in the product term). Or cast a in the myResult calculation to int64: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var a, b, c, d : longint;      myResult : Int64;...  a := 828;  b := 653;  c := 12362752;  d := 552;           myResult := ((Int64(a)-b)*c) div d; ---------------------------------------------------------------------- Apollo286 · 2021-01-05 22:41 Thank you for answer (and sorry for my english).  processor: AMD A10-7800 fpc version:   Ubuntu 20.04 64bit - fpc-laz 3.2.0                      Windows 10  64bit - fpc 3.2.0 compiler mode: {$mode objfpc} ---------------------------------------------------------------------- Remy Lebeau · 2021-01-05 22:45 Quote from: Apollo286 on January 05, 2021, 11:03:06 pmLazarus 2.0.10, in Ubuntu:        myResult = 3919350              That is the correct result when Longint is 64bits in size. Quote from: Apollo286 on January 05, 2021, 11:03:06 pmLazarus 2.0.10, in Windows:     myResult = -3861387 That is the correct result when Longint is 32bits in size. Quote from: Apollo286 on January 05, 2021, 11:03:06 pmThe same code, but two different results. Because you are operating on a data type that has different sizes on different platforms. Quote from: Apollo286 on January 05, 2021, 11:03:06 pmI think - problem is with integer division Actually, the problem is with the integer multiplication. When Longint is 32bits, the result of ((a-b)*c) (((828-653)*12362752) = 2163481600) overflows the max value of Longint (2147483647), so the result of the multiplication is a negative value (-2131485696), then the result of the integer division is also negative (-2131485696 / 552 = -3861387). When Longint is 64bits, there is no overflow. ---------------------------------------------------------------------- Apollo286 · 2021-01-05 23:06 Quote from: wp on January 05, 2021, 11:40:35 pmYour calculation in myResult has an integer overflow. Turn on the "I/O overflow" box in the Debugging page of the Project options to get an error message. To fix the problem declare all longint as Int64 (or at least one of the factors in the product term). Or cast a in the myResult calculation to int64: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var a, b, c, d : longint;      myResult : Int64;...  a := 828;  b := 653;  c := 12362752;  d := 552;           myResult := ((Int64(a)-b)*c) div d; Thank you very much, this was the problem... Longint to Int64 and problem is solved.    But I still dont understand: For valid result in Ubuntu is Longint enough, but in Win version of fpc I need Int64? ---------------------------------------------------------------------- Apollo286 · 2021-01-05 23:12 Quote from: Remy Lebeau on January 05, 2021, 11:45:41 pm... Because you are operating on a data type that has different sizes on different platforms. ... Actually, the problem is with the integer multiplication. ... When Longint is 64bits, there is no overflow. Thank you for explaining.  Your answer is excellent. ---------------------------------------------------------------------- wp · 2021-01-05 23:19 Quote from: Remy Lebeau on January 05, 2021, 11:45:41 pmThat is the correct result when Longint is 64bits in size. This statement confuses me a lot: I always thought that longint is 32 bit: https://www.freepascal.org/docs-html/3.0.2/ref/refsu4.html. ---------------------------------------------------------------------- Blaazen · 2021-01-06 00:50 LongInt is never 64-bit. The reason is how the formula is treated on 64-bt Linux. The result of multiplication is stored to 64-bit register, therefore it gives correct result without overflow even if myResult is 32-bit. ---------------------------------------------------------------------- PascalDragon · 2021-01-06 10:06 Quote from: Apollo286 on January 05, 2021, 11:41:24 pmThank you for answer (and sorry for my english).  processor: AMD A10-7800 fpc version:   Ubuntu 20.04 64bit - fpc-laz 3.2.0                      Windows 10  64bit - fpc 3.2.0 compiler mode: {$mode objfpc} Are you sure that you're compiling for 64-bit on Windows? Cause I get that result (-3861387) only if I compile for i386. Also you could enable range and overflow checks (command line options -Cro or directives {$R+}{$Q+}) and you'd see that you got a problem in the case where result is -3861387. ---------------------------------------------------------------------- Apollo286 · 2021-01-06 12:13 Quote from: PascalDragon on January 06, 2021, 11:06:41 amQuote from: Apollo286 on January 05, 2021, 11:41:24 pmThank you for answer (and sorry for my english).  processor: AMD A10-7800 fpc version:   Ubuntu 20.04 64bit - fpc-laz 3.2.0                      Windows 10  64bit - fpc 3.2.0 compiler mode: {$mode objfpc} Are you sure that you're compiling for 64-bit on Windows? Cause I get that result (-3861387) only if I compile for i386. Also you could enable range and overflow checks (command line options -Cro or directives {$R+}{$Q+}) and you'd see that you got a problem in the case where result is -3861387. Both systems Ubuntu and Windows are 64bit, but I don't know how the code is compiling on each system (maybe 32-bit on Win and 64-bit on Ubu - I used default installation of Lazarus)... For me now - after redeclaring variables to Int64, code is working with no integer owerflow. ---------------------------------------------------------------------- Bart · 2021-01-06 12:14 Windows defaults to compiling 32-bit. On *nix 64-bit you will also have by default a 64-bit compiler. Bart ---------------------------------------------------------------------- lucamar · 2021-01-06 12:50 Quote from: Bart on January 06, 2021, 01:14:29 pmWindows defaults to compiling 32-bit. That depends on which installer you did run, doesn't it? If you run the 64 bit one then it'll install the 64bit compiler (and everything else). Would be nice to see the output of:Code: [Select]fpc -i(at least the section "Supported targets") on the OP's Windows install. ---------------------------------------------------------------------- Remy Lebeau · 2021-01-06 18:54 Quote from: Blaazen on January 06, 2021, 01:50:12 amLongInt is never 64-bit. Good point.  I was thinking of Delphi's LongInt, which does float between 32bit and 64bit sizes depending on platform (whereas Integer and FixedInt are always 32bit). How does FreePascal handle C-based platform APIs that use 64bit long? Quote from: Blaazen on January 06, 2021, 01:50:12 amThe reason is how the formula is treated on 64-bt Linux. The result of multiplication is stored to 64-bit register, therefore it gives correct result without overflow even if myResult is 32-bit. Good point. ---------------------------------------------------------------------- howardpc · 2021-01-06 19:26 You can use the ctypes unit, which includes these: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  cint8                  = UnixType.cint8;       pcint8                 = UnixType.pcint8;  cuint8                 = UnixType.cuint8;      pcuint8                = UnixType.pcuint8;  cchar                  = UnixType.cchar;       pcchar                 = UnixType.pcchar;  cschar                 = UnixType.cschar;      pcschar                = UnixType.pcschar;  cuchar                 = UnixType.cuchar;      pcuchar                = UnixType.pcuchar;   cint16                 = UnixType.cint16;      pcint16                = UnixType.pcint16;  cuint16                = UnixType.cuint16;     pcuint16               = UnixType.pcuint16;  cshort                 = UnixType.cshort;      pcshort                = UnixType.pcshort;  csshort                = UnixType.csshort;     pcsshort               = UnixType.pcsshort;  cushort                = UnixType.cushort;     pcushort               = UnixType.pcushort;   cint32                 = UnixType.cint32;      pcint32                = UnixType.pcint32;  cuint32                = UnixType.cuint32;     pcuint32               = UnixType.pcuint32;  cint                   = UnixType.cint;        pcint                  = UnixType.pcint;  csint                  = UnixType.csint;       pcsint                 = UnixType.pcsint;  cuint                  = UnixType.cuint;       pcuint                 = UnixType.pcuint;  csigned                = UnixType.csigned;     pcsigned               = UnixType.pcsigned;  cunsigned              = UnixType.cunsigned;   pcunsigned             = UnixType.pcunsigned;   cint64               = UnixType.cint64;      pcint64                = UnixType.pcint64;  cuint64                = UnixType.cuint64;     pcuint64               = UnixType.pcuint64;  clonglong              = UnixType.clonglong;   pclonglong             = UnixType.pclonglong;  cslonglong             = UnixType.cslonglong;  pcslonglong            = UnixType.pcslonglong;  culonglong             = UnixType.culonglong;  pculonglong            = UnixType.pculonglong;   cbool                = UnixType.cbool;       pcbool                 = UnixType.pcbool;   clong                  = UnixType.clong;       pclong                 = UnixType.pclong;  cslong                 = UnixType.cslong;      pcslong                = UnixType.pcslong;  culong                 = UnixType.culong;      pculong                = UnixType.pculong; {$ifndef FPUNONE}  cfloat                 = UnixType.cfloat;      pcfloat                = UnixType.pcfloat;  cdouble                = UnixType.cdouble;     pcdouble               = UnixType.pcdouble;//  clongdouble            = UnixType.clongdouble; pclongdouble           = UnixType.pclongdouble;{$endif}   csize_t              = UnixType.size_t;      pcsize_t               = UnixType.psize_t;   coff_t                 = UnixType.TOff; ---------------------------------------------------------------------- PascalDragon · 2021-01-07 08:04 Quote from: Remy Lebeau on January 06, 2021, 07:54:33 pmHow does FreePascal handle C-based platform APIs that use 64bit long? When interfacing with C code it's suggested to use the types from the ctypes unit (in this case clong) as these are defined according to the platform (and for the Windows API it's of course suggested to use the appropriate types from the Windows unit ).