What is the equivalent Delphi code for this multiplication by C, resulting in a large number?

Background for this question ... I am trying to port the function C int popcount_3(uint64_t x) from Wikipedia: Hamming's weight , but its algorithm is not the subject of this question.

Let's say x is the maximum number of 64-bit unsigned values ​​( x = 18446744073709551615 ), at the end of the calculation, the C code will calculate:

 uint64_t iResult = 578721382704613384ull * 72340172838076673ull; 

Firstly, I suspected that the C code caused an overflow error because the actual / real result of the operation when using floating point multiplication is 41864804849942400000000000000000000 , but the error for this C code is not actually compiled. Output signal 4627501566018457608 .

As you know, the Delphi code for the above C code will be:

 iResult := UInt64(578721382704613384) * UInt64(72340172838076673); 

Delphi compiler causes error E2099 Overflow in conversion or arithmetic operation . Well, I see that the error is reasonable.

So my question is ... What is the equivalent Delphi code for multiplying oversized numbers, so that Delphi gives the same result as in C?

Added later

To anticipate the upcoming potential question, "Why did I set an example using a true constant expression?" , the reason is that I want to create a true constant that calculates the number of bits per computer word by counting the number of bits set in High(NativeUInt) .

Playback Steps

GCC 4.8.1 (MinGW)

 #include <stdio.h> #include <stdint.h> int main () { uint64_t iResult = 578721382704613384ull * 72340172838076673ull; printf("iResult = %llu\n", iResult); // output --> 4627501566018457608 return 0; } 

Delphi XE3 in 64-bit Windows compiler mode

 procedure Test; var iResult : UInt64; RealResult: Double; begin iResult := UInt64(578721382704613384) * UInt64(72340172838076673); RealResult := 578721382704613384.0 * 72340172838076673.0; WriteLn('iResult = ', iResult); // error --> E2099 Overflow in ... WriteLn('RealResult = ', RealResult); // output --> 4.18648048499424E+0034 end; 
+6
source share
1 answer

The Delphi compiler attempts to evaluate the constant expression UInt64(578721382704613384) * UInt64(72340172838076673) during compilation and reports an overflow error.

The solution uses the variables:

 var iResult, i1, i2 : UInt64; RealResult: Double; begin i1 := 578721382704613384; i2 := 72340172838076673; iResult := i1 * i2; RealResult := 578721382704613384.0 * 72340172838076673.0; 

This code creates the desired result.

Please note that the Overflow check flag in the project settings must be turned off. Or use compiler directives in type code

  {$OVERFLOWCHECKS OFF} iResult := i1 * i2; {$OVERFLOWCHECKS ON} 

Edit Based on @hvd warning

These directives only make sense if the options for the Overflow check project are On . If not, these directives can be omitted.

The third method, most often and universal, uses the directive {$ ifopt ...} (@hvd, thanks again):

 {$ifopt Q+} // If option is On ... {$Q-} // then turn it Off ... {$define TURNQON} // and keep in mind that it must be restored {$endif} iResult := i1 * i2; {$ifdef TURNQON}{$Q+}{$undef TURNQON}{$endif} 

However, the best way is to use the already calculated desired result, then such tricks.

+3
source

All Articles