Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
这个C乘法的等价Delphi代码是什么?_Delphi_Delphi Xe3 - Fatal编程技术网

这个C乘法的等价Delphi代码是什么?

这个C乘法的等价Delphi代码是什么?,delphi,delphi-xe3,Delphi,Delphi Xe3,这个问题的背景是。。。我试图从中移植C函数intpopcount\u3(uint64\utx),但它的算法不是这个问题的重点 假设x是无符号64位值的最大数目(即x=18446744073709551615),在计算结束时,C代码将计算: uint64\u t iResult=5787213822704613384ull*7234017838076673ull; 首先,我怀疑C代码引发了溢出错误,因为使用浮点乘法时操作的实际/实际结果等于4186484994240000000000000000

这个问题的背景是。。。我试图从中移植C函数
intpopcount\u3(uint64\utx)
,但它的算法不是这个问题的重点

假设
x
是无符号64位值的最大数目(即x=18446744073709551615),在计算结束时,C代码将计算:

uint64\u t iResult=5787213822704613384ull*7234017838076673ull;
首先,我怀疑C代码引发了溢出错误,因为使用浮点乘法时操作的实际/实际结果等于41864849942400000000000000000000000000000000,但事实上,该C代码没有编译错误。输出为4627501566018457608

如我们所知,上述C代码的Delphi代码为:

iResult:=UInt64(578721382704613384)*UInt64(72340172838076673);
Delphi编译器在转换或算术运算中引发错误E2099溢出。好的,我看这个错误是合理的

所以,我的问题是。。。对于超大数字的乘法,Delphi给出与C中相同的结果的等效Delphi代码是什么

后来添加 为了预测即将出现的潜在问题“我为什么使用真常量表达式提供示例?”,原因是我想创建一个真常量,通过计算
高(NativeUInt)
中的设置位数来计算中的位数

复制步骤 通用条款4.8.1(MinGW)

#包括
#包括
int main(){
uint64\u t iResult=578721382704613384ull*72340172838076673ull;
printf(“iResult=%llu\n”,iResult);//输出-->4627501566018457608
返回0;
}
64位Windows编译器模式下的Delphi XE3

程序测试;
变量
结果:UInt64;
实际结果:加倍;
开始
i结果:=UInt64(578721382704613384)*UInt64(72340172838076673);
真实结果:=578721382704613384.0*72340172838076673.0;
WriteLn('iResult=',iResult);//错误-->E2099溢出位于。。。
WriteLn('RealResult=',RealResult);//输出-->4.18648499424E+0034
结束;

Delphi编译器在编译时尝试计算常量表达式
UInt64(57872138282704613384)*UInt64(72340172838076673)
,并向您报告溢出错误

解决方案是使用变量:

var
  iResult, i1, i2   : UInt64;
  RealResult: Double;

begin
  i1 := 578721382704613384;
  i2 := 72340172838076673;
  iResult := i1 * i2;
  RealResult := 578721382704613384.0 * 72340172838076673.0;
此代码生成所需的结果

请注意,项目选项中的
溢出检查
标志必须关闭。或者在代码中使用编译器指令,如

  {$OVERFLOWCHECKS OFF}
  iResult := i1 * i2;
  {$OVERFLOWCHECKS ON}
根据@hvd的警告进行编辑

只有在项目的选项中
溢出检查
打开时,这些指令才有意义。如果没有,则可以省略这些指令

第三种方法,最常见也是最普遍的,是使用{$ifopt…}指令(@hvd,再次感谢):


然而,更好的方法是使用已经计算出的期望结果,而不是这些技巧。

编译器不能将其作为一个真正的常量进行计算,这是相当令人恼火的。考虑到德尔菲的时代,很难相信他们忽略了这样一件小事。@DavidHeffernan-我只是想澄清一下,我所说的“他们”是什么意思警告:如果项目设置中的OVERFLOWCHECKS处于禁用状态,则编译器指令将在文件的其余部分启用它。要尊重文件其余部分的项目设置,您需要
$IFOPT
来确定是否启用了
溢出检查
,并且只有在它之前打开时才将其打开。@Abelisto-在这种情况下不可能预先计算所需结果,因为所需结果取决于传递给
int popcount_3(uint64_t x)
x
的值。虽然您的可变利用率技巧不适用于我的问题(请参阅我的更新)中描述的情况,但您的技巧对我仍然有用。看来没有别的办法解决我的问题了。由于我的错误没有全面描述问题,我还是接受你的回答。干杯:-)@Aeoliyan我不明白这句话。如果操作数只在运行时已知,那么您根本不能使用常量。@David Heffernan-不,在我的例子中,操作数可以在编译时已知,即
High(NativeUInt)
。我使用
int-popcount\u 2
函数而不是
int-popcount\u 3
成功地获得了计算机字中的位数。我在
const
部分中把它作为真常量来做__ciC06=UInt64(uuu ciMaxCpuWord-(uuu ciMaxCpuWord shr 1)和UInt64($555555))__ciC07=UInt64((uu ciC06和UInt64($3333))+(uu ciC06 shr 2)和UInt64($3333))__ciC08=UInt64((uu ciC07+(uu ciC07 shr 4))和UInt64($0F0F))__ciC09=UInt64(uu ciC08+(uu ciC08 shr 8))__ciC10=UInt64(uuCIC09+(uuuCIC09 shr 16))__ciC11=UInt64(uuCIC10+(uuuCIC10 shr 32));ciNumBitsInCpuWord=uuuu ciC11和UInt64($000000000000007F);
{$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}