What is the right way to find the average of two values?

后端 未结 8 1139
北荒
北荒 2021-02-19 00:58

I recently learned that integer overflow is an undefined behavior in C (side question - is it also UB in C++?)

Often in C programming you need to find the average of two

8条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-02-19 01:07

    This is from Calculating the average of two integer numbers rounded towards zero in a single instruction cycle:

    (a >> 1) + (b >> 1) + (a & b & 0x1)
    

    You must consider that:

    • it's implementation defined whether right shifting a negative integer shifts zeros or ones into the high order bits. Many CPUs often have two different instructions: an arithmetic shift right (preserves the sign bit) and a logical shift right (doesn't preserve the sign bit). The compiler is allowed to choose either (most compilers choose an arithmetic shift instruction).

      ISO/IEC 9899:2011 §6.5.7 Bitwise shift operators

      ¶5 The result of E1 >> E2is E1 right-shifted E2 bit positions. [CUT] If E1 has a signed type and a negative value, the resulting value is implementation-defined.

      Changing the expression to:

      a / 2 + b / 2 + (a & b & 0x1)
      

      isn't a solution since logical right shifts are equivalent to division by a power of 2 only for positive or unsigned numbers.

    • also (a & b & 0x1) isn't well defined. This term should be non-zero when both a and b are odd. But it fails with one's complement representation and ISO C, section 6.2.6.2/2, states that an implementation can choose one of three different representations for integral data types:

      • two's complement
      • one's complement
      • sign/magnitude

      (usually the two's complement far outweigh the others).

提交回复
热议问题