按位C $ C $Ç四舍五入问题 [英] Rounding issues with bitwise C code
问题描述
我有以下按位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
double
s 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屋!