【问题标题】:SHR on int64 does not return expected resultint64 上的 SHR 不返回预期结果
【发布时间】:2014-02-21 17:21:05
【问题描述】:

我正在将一些 C# 代码移植到 Delphi (XE5)。 C# 代码有这样的代码:

long t = ...
...                
t = (t >> 25) + ...

我把它翻译成

t: int64;
...
t := (t shr 25) + ...

现在我看到 Delphi(有时)为移动负 t 计算错误的值,例如:

-170358640930559629 shr 25
Windows Calculator: -5077083139
C# code: -5077083139

Delphi: 
-170358640930559629 shr 25               = 544678730749 (wrong)

对于这个例子,-1*((-t shr 25)+1) 在 Delphi 中给出了正确的值。

对于 t 的其他负值,一个简单的整数类型转换似乎给出了正确的结果:

integer(t shr 25)

我在二进制运算和表示方面已处于极限,因此如果能在 Delphi 中获得与 C# 和 Windows 计算器中相同的结果,我将不胜感激。

【问题讨论】:

标签: delphi delphi-xe5 int64


【解决方案1】:

基于 Filipe 的 answer 中链接的 article(说明了 Delphi 执行 shr 而其他人执行 sar 的原因),这是我对此的看法:

function CalculatorRsh(Value: Int64; ShiftBits: Integer): Int64;
begin
  Result := Value shr ShiftBits;
  if (Value and $8000000000000000) > 0 then
    Result := Result or ($FFFFFFFFFFFFFFFF shl (64 - ShiftBits));
end;

【讨论】:

  • +1。这很好用。当“Value”为负数时,它将由shr 放置的最左边的0 位替换为正确的1 位。 and 条件等价于Value < 0
  • @JRL - 谢谢!您认为在这里使“阴性”测试更具可读性会更好吗?毕竟它涉及一些位移..
  • 32 位整数的相同函数看起来像这样吗?函数CalculatorRsh(值:整数; ShiftBits:整数):整数;开始结果 := 值 shr ShiftBits; if (Value and $80000000) > 0 then Result := Result or ($FFFFFFFF shl (32 - ShiftBits));结束;
  • @user - 现在试了一下,它在 $FFFFFFFF 上给出了一个范围检查错误(如果范围检查已打开),将其转换为整数,或替换为 -1。
【解决方案2】:

如您所见here,C 和 Delphi 对待 Shr 的方式是不同的。不是指指点点,但 C 的 >> 并不是真正的 shr,它实际上是 sar。 无论如何,我发现的唯一解决方法是手动进行数学运算。这是一个例子:

function SAR(a, b : int64): int64;
begin
  result := round(a / (1 shl b));
end;

希望对你有帮助!

【讨论】:

  • 您的 SAR 函数似乎是 1:SAR(-1841198311509,25) 返回 -54871,而 Windows Calc 返回 -54872。
  • 刚改了功能,看看你的想法。它已在答案处进行了编辑。
  • @GJ。 - 查看修订历史,以及对答案的第一条评论。
  • round(a / (1 shl b))a div (1 shl b))a = -5b = 1 时都失败。两者都返回 -2 而不是 -3
  • 那篇文章的来源很差。 C 的 >>实现定义 用于负操作数的,因此将其与 Delphi 的移位运算符进行比较是没有帮助的。最好与 C# 进行比较,就像问题一样。
猜你喜欢
  • 2016-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-07
相关资源
最近更新 更多