简体   繁体   English

将 64 位整数四舍五入为 32 位整数

[英]Rounding 64 bit integers to 32 bit integers

I have a function that does rounding operation as shown below.我有一个执行四舍五入操作的函数,如下所示。 It takes 64bit integer as input and gives 32bit integer as output.它以 64 位整数作为输入,并给出 32 位整数作为输出。 While converting, a factor of 0x40000000 is being added to the input.转换时,输入中会添加 0x40000000 的因子。 What is the reason behind it?背后的原因是什么?

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;
}

Let's start with some smaller numbers, because they're easier!让我们从一些较小的数字开始,因为它们更容易!

Using conventional rounding, x.49999... or less should round down to x, x.50000... or more should round up to (x+1).使用常规四舍五入,x.49999...或更小应该四舍五入到x,x.50000...或更多应该四舍五入到(x+1)。

(There are lots of different rounding methods, but this is the one most learn at school.) (有很多不同的舍入方法,但这是在学校学得最多的一种。)

Whenever you do integer division (or conversion of a floating point value to an integer), you simply throw away the fractional part.每当您进行整数除法(或将浮点值转换为整数)时,您只需扔掉小数部分即可。 Hence:因此:

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

A neat 'trick' is to add half-the-divisor (1, in this case) before division.一个巧妙的“技巧”是在除法之前添加除数的一半(在本例中为 1)。 As if by magic, you get the right rounding!就像魔法一样,你得到了正确的四舍五入! eg:例如:

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

You can see why this works by looking at it this way:您可以通过以下方式查看它的工作原理:

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

You're adding half to the real answer.你在真正的答案上加了一半。 Anything less than x.5 will still be less than x+1 so will still round down, anything of x.5 or more will become x+1 or more so will round up.任何小于 x.5 的值仍将小于 x+1,因此仍会向下舍入,x.5 或更大的值将变为 x+1 或更大,因此将向上舍入。

Now to your actual question: This idea works with all divisors;现在回答您的实际问题:这个想法适用于所有除数; you're shifting down by 31, which is the same as dividing by 2^31.您向下移动 31,这与除以 2^31 相同。 So 'half-the-divisor' is 2^30, or 0x40000000.所以“除数的一半”是 2^30,或 0x40000000。

Beware: as others have noted, this 'trick' only works for positive numbers (you need to subtract if it's negative, but it's a can of worms).当心:正如其他人所指出的,这个“技巧”只适用于正数(如果它是负数,你需要减去,但它是一堆蠕虫)。

There is a lot to consider in this topic;这个话题有很多东西需要考虑; it's not simple to get your head around.转过头来并不容易。 As ever, try some easy examples for yourself and see what happens.一如既往,为自己尝试一些简单的例子,看看会发生什么。

The input appears to be a 64-bit fixed point number with 31 fraction bits.输入似乎是一个带有 31 个小数位的 64 位定点数。 The 0x40000000 value is added to round the number up if it has a fractional part >= 0.5.如果小数部分 >= 0.5,则添加 0x40000000 值以向上舍入该数字。 The if is used to avoid possible overflow when factoring in the rounding. if用于在考虑舍入时避免可能的溢出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM