【问题标题】:Rounding 64 bit integers to 32 bit integers将 64 位整数舍入为 32 位整数
【发布时间】:2020-02-20 04:38:49
【问题描述】:

我有一个函数可以进行舍入操作,如下所示。它以 64 位整数作为输入,并给出 32 位整数作为输出。转换时,0x40000000 的因子被添加到输入中。背后的原因是什么?

int rounder(long long int in)
{
  INT64 out;
  if ((in >> 32) == 0x7FFFFFFF)
    out = in;
  else
    out = (INT64)0x40000000 + in; 
  out = out >> 31; 
  return (INT32)out;
}

【问题讨论】:

  • 我没有看到 var 习惯了
  • 请显示INT64和INT32的定义,以及你得到的样本输入和输出。最好发stackoverflow.com/help/minimal-reproducible-example
  • @EduardoPascualAseff..嗨,我已经编辑了代码
  • 负值舍入不正确。
  • return (INT32)out 对于 out 附近的 LLONG_MAX 值不正确。这段代码有很多错误。

标签: c rounding int64 int32


【解决方案1】:

让我们从一些较小的数字开始,因为它们更容易!

使用常规舍入,x.49999... 或更小应向下舍入为 x,x.50000... 或更大应向上舍入为 (x+1)。

(有lots不同的取整方法,但这是在学校学得最多的一种。)

每当您进行整数除法(或将浮点值转换为整数)时,您只需丢弃小数部分。因此:

6/2 == 3.0  --> 3
5/2 == 2.5  --> 2

一个巧妙的“技巧”是在除法之前添加一半的除数(在本例中为 1)。就像变魔术一样,你得到了正确的四舍五入!例如:

6/2  becomes  (6+1)/2  == 7/2 == 3.5  --> 3
5/2  becomes  (5+1)/2  == 6/2 == 3.0  --> 3

您可以通过以下方式了解其工作原理:

 5/2  becomes  (5+1)/2  ==   5/2 + 1/2
13/6  becomes (13+3)/6  ==  13/6 + 3/6   == 13/6 + 1/2

你给真实答案加了一半。任何小于 x.5 的值仍将小于 x+1,因此仍会向下舍入,x.5 或更大的任何值将变为 x+1 或更大,因此将向上舍入。

现在回答您的实际问题: 这个想法适用于所有除数;您将向下移动 31,这与除以 2^31 相同。所以“除数的一半”是 2^30,即 0x40000000。

当心:正如其他人所指出的,这个“技巧”只适用于正数(如果它是负数,你需要减去,但它是一罐蠕虫)。

这个话题有很多需要考虑的地方;让你的头脑四处走动并不容易。和以往一样,为自己尝试一些简单的例子,看看会发生什么。

【讨论】:

    【解决方案2】:

    输入似乎是一个带有 31 个小数位的 64 位定点数。如果小数部分 >= 0.5,则添加 0x40000000 值以将数字向上舍入。 if 用于在考虑舍入时避免可能的溢出。

    【讨论】:

    • 您好,您的回答似乎对我有帮助。能详细解释一下吗?
    • 定点数是整数,其中您在两个定义的位之间有一个假想的“小数点”(实际上是一个“二进制点”;-)。左边是整数部分,右边是小数部分。
    猜你喜欢
    • 1970-01-01
    • 2019-12-16
    • 1970-01-01
    • 2019-08-17
    • 2019-03-25
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    相关资源
    最近更新 更多