按位C $ C $Ç四舍五入问题 [英] Rounding issues with bitwise C code

查看:278
本文介绍了按位C $ C $Ç四舍五入问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下按位code这蒙上了浮点值(封装在一个int)为int值。

问:有四舍五入问题,所以它的情况下失败的地方输入0x80000001为例。我该如何处理呢?

下面是code:

 如果(X == 0)返回X;  unsigned int类型signBit = 0;
  unsigned int类型absX =(unsigned int类型)×;
  如果(X℃,)
  {
      signBit = 0x80000000u;
      absX =(unsigned int类型)-x;
  }  无符号整型指数= 158;
  而((absX&安培;为0x80000000)== 0)
  {
      指数 -​​ ;
      absX&所述;&下; = 1;
  }  unsigned int类型尾数= absX>> 8;  无符号整型结果= signBit | (指数<< 23)| (尾数&安培; 0x7fffff);
  的printf(\\ n对于X:为%x,结果是:%X,X,结果);
  返回结果;


解决方案

这是因为precision 0x80000001 超出的一个浮动 。阅读链接的文章,一个浮动的precision为24位,所以任何对彩车的差异(说明X - Y )小于的最高位两个>> 24 根本无法被检测到。
  GDB 同意你的施法:

main.c中:

 的#include<&stdio.h中GT;诠释主(){
    浮动X = 0x80000001;
    的printf(%F \\ N,X);
    返回0;
}

GDB:

 断点1,主要的()在test.c的:4
4浮动X = 0x80000001;
(GDB)N
5的printf(%F \\ N,X);
(GDB)P X [
$ 1 = 2.14748365e + 09
(GDB)P(INT)x
$ 2 = -2147483648
(GDB)P / X(INT)x
$ 3 = 0x80000000的
(GDB)

这IM precision的限制:

 (GDB)芘为0x80000000 ==(浮点)0x80000080
$ 21 = 1
(GDB)p为0x80000000 ==(浮点)0x80000081
$ 20 = 0

实际按位重新presentation:

 (GDB)P / X(INT)(无效*)(浮点)为0x80000000
$ 27 = 0x4f000000
(GDB)P / X(INT)(无效*)(浮点)0x80000080
$ 28 = 0x4f000000
(GDB)P / X(INT)(无效*)(浮点)0x80000081
$ 29 = 0x4f000001

双击就做有足够的precision做出区分:

 (GDB)芘为0x80000000 ==(浮点)0x80000001
$ 1 = 1
(GDB)p为0x80000000 ==(双)0x80000001
$ 2 = 0

I have to following bitwise code which casts a floating point value (packaged in an int) to an int value.

Question: There are rounding issues so it fails in cases where input is 0x80000001 for example. How do I handle this?

Here is the code:

  if(x == 0) return x;

  unsigned int signBit = 0;
  unsigned int absX = (unsigned int)x;
  if (x < 0)
  {
      signBit = 0x80000000u;
      absX = (unsigned int)-x;
  }

  unsigned int exponent = 158;
  while ((absX & 0x80000000) == 0)
  {
      exponent--;
      absX <<= 1;
  }

  unsigned int mantissa = absX >> 8;

  unsigned int result = signBit | (exponent << 23) | (mantissa & 0x7fffff);
  printf("\nfor x: %x, result: %x",x,result);
  return result;

解决方案

That's because the precision of 0x80000001 exceeds that of a float. Read the linked article, the precision of a float is 24 bits, so any pair of floats whose difference (x - y) is less than the highest bit of the two >> 24 simply cannot be detected. gdb agrees with your cast:

main.c:

#include <stdio.h>

int main() {
    float x = 0x80000001;
    printf("%f\n",x);
    return 0;
}

gdb:

Breakpoint 1, main () at test.c:4
4       float x = 0x80000001;
(gdb) n
5       printf("%f\n",x);
(gdb) p x
$1 = 2.14748365e+09
(gdb) p (int)x
$2 = -2147483648
(gdb) p/x (int)x
$3 = 0x80000000
(gdb) 

The limit of this imprecision:

(gdb) p 0x80000000 == (float)0x80000080 
$21 = 1
(gdb) p 0x80000000 == (float)0x80000081
$20 = 0

The actual bitwise representation:

(gdb) p/x (int)(void*)(float)0x80000000
$27 = 0x4f000000
(gdb) p/x (int)(void*)(float)0x80000080
$28 = 0x4f000000
(gdb) p/x (int)(void*)(float)0x80000081
$29 = 0x4f000001

doubles do have enough precision to make the distinction:

(gdb) p 0x80000000 == (float)0x80000001
$1 = 1
(gdb) p 0x80000000 == (double)0x80000001
$2 = 0

这篇关于按位C $ C $Ç四舍五入问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆