Floating point 将无符号整数转换为仅包含整数运算的单精度浮点
这个想法是为了让它和这个做几乎相同的事情 例如,如果我插入357,我应该得到0x43b28000Floating point 将无符号整数转换为仅包含整数运算的单精度浮点,floating-point,Floating Point,这个想法是为了让它和这个做几乎相同的事情 例如,如果我插入357,我应该得到0x43b28000 float unsignedToFloat( unsigned int x ) { unsigned int result = 0; return *(float*)&result; } 但是我该怎么做呢 我看到了这一点,但似乎没有任何好的解决方案。首先,如果x为零,则返回零 接下来在x中查找最高阶非零位的索引。叫它i 如果i小于24,将x左移23-i,以获得标准化的有效位。现在清除
float unsignedToFloat( unsigned int x ) {
unsigned int result = 0;
return *(float*)&result;
}
但是我该怎么做呢
我看到了这一点,但似乎没有任何好的解决方案。首先,如果
x
为零,则返回零
接下来在x
中查找最高阶非零位的索引。叫它i
如果i
小于24,将x
左移23-i
,以获得标准化的有效位。现在清除位23以隐藏隐式位,并将位23:30设置为127+i
,这是有偏指数。返回结果
否则,将x
右移i-23
,通过截断获得标准化的有效位,然后清除隐式位并如上所述设置指数。如果您想要的舍入模式是截断或舍入到负无穷大,那么就完成了。否则,您需要查看从x
底部移位的位。如果所需的舍入模式是舍入到正无穷大,并且设置了这些位中的任何一位,则在结果中添加一位并返回。最后,如果所需的舍入模式是舍入到最接近的偶数(IEEE-754默认值),则有三种情况:
- 尾随位是
:返回截断的结果b0…
- 尾随位是
:这是一个精确的中间情况。如果调用截断的结果b1000…
,则需要返回t
;i、 e.仅当t+(t&1)
为奇数时,才进行取整t
- 尾随位是
:向截断的结果中添加一位并返回b1…1…
x
为零,则返回零
接下来在x
中查找最高阶非零位的索引。叫它i
如果i
小于24,将x
左移23-i
,以获得标准化的有效位。现在清除位23以隐藏隐式位,并将位23:30设置为127+i
,这是有偏指数。返回结果
否则,将x
右移i-23
,通过截断获得标准化的有效位,然后清除隐式位并如上所述设置指数。如果您想要的舍入模式是截断或舍入到负无穷大,那么就完成了。否则,您需要查看从x
底部移位的位。如果所需的舍入模式是舍入到正无穷大,并且设置了这些位中的任何一位,则在结果中添加一位并返回。最后,如果所需的舍入模式是舍入到最接近的偶数(IEEE-754默认值),则有三种情况:
- 尾随位是
:返回截断的结果b0…
- 尾随位是
:这是一个精确的中间情况。如果调用截断的结果b1000…
,则需要返回t
;i、 e.仅当t+(t&1)
为奇数时,才进行取整t
- 尾随位是
:向截断的结果中添加一位并返回b1…1…
- 我是这样做的:
更新
这一个正确处理0、INT_MIN和舍入,AFAICT:
#define SIGN_MASK (1 << 31)
#define HIDDEN_MASK (1 << 23)
#define MANTISSA_MASK (HIDDEN_MASK - 1)
#define INT_MIN 0x80000000
#define INT_MAX 0x7FFFFFFF
float intToFloat(int n)
{
int sign;
int exp;
unsigned int half;
if (n == 0)
return 0.0f;
if (n == INT_MIN)
return -(float)(INT_MIN);
sign = n < 0 ? SIGN_MASK : 0;
if (sign)
n = -n;
if (!(n & ~(HIDDEN_MASK | MANTISSA_MASK)))
for (exp = 0; !(n & HIDDEN_MASK); n <<= 1, exp--) ;
else
{
half = 0;
for (exp = 0; n & ~(HIDDEN_MASK | MANTISSA_MASK); exp++)
{
half >>= 1;
if (n & 1)
half |= 0x80000000;
n >>= 1;
}
if (half > INT_MIN || ((half == INT_MIN) && (n & 1) != 0))
{
n++;
if (n == 0x1000000)
{
n = 0; // or 0x800000, doesn't matter.
exp++;
}
}
}
exp = (exp + 127 + 23) << 23;
n = (n & MANTISSA_MASK) | sign | exp;
return *((float *)&n);
}
定义符号掩码(1=1;
}
如果(一半>整数最小值((一半==整数最小值)和&(n&1)!=0))
{
n++;
如果(n==0x1000000)
{
n=0;//或0x800000,这无关紧要。
exp++;
}
}
}
exp=(exp+127+23)我是这样做的:
更新
这一个正确处理0、INT_MIN和舍入,AFAICT:
#define SIGN_MASK (1 << 31)
#define HIDDEN_MASK (1 << 23)
#define MANTISSA_MASK (HIDDEN_MASK - 1)
#define INT_MIN 0x80000000
#define INT_MAX 0x7FFFFFFF
float intToFloat(int n)
{
int sign;
int exp;
unsigned int half;
if (n == 0)
return 0.0f;
if (n == INT_MIN)
return -(float)(INT_MIN);
sign = n < 0 ? SIGN_MASK : 0;
if (sign)
n = -n;
if (!(n & ~(HIDDEN_MASK | MANTISSA_MASK)))
for (exp = 0; !(n & HIDDEN_MASK); n <<= 1, exp--) ;
else
{
half = 0;
for (exp = 0; n & ~(HIDDEN_MASK | MANTISSA_MASK); exp++)
{
half >>= 1;
if (n & 1)
half |= 0x80000000;
n >>= 1;
}
if (half > INT_MIN || ((half == INT_MIN) && (n & 1) != 0))
{
n++;
if (n == 0x1000000)
{
n = 0; // or 0x800000, doesn't matter.
exp++;
}
}
}
exp = (exp + 127 + 23) << 23;
n = (n & MANTISSA_MASK) | sign | exp;
return *((float *)&n);
}
定义符号掩码(1=1;
}
如果(一半>整数最小值((一半==整数最小值)和&(n&1)!=0))
{
n++;
如果(n==0x1000000)
{
n=0;//或0x800000,这无关紧要。
exp++;
}
}
}
Exp=(Exp+127+23)如果你使用C++,你可以使用RealTytRayCask.我不明白.你的函数返回一个浮点.它怎么能返回<代码> 0x43B2800< /代码>?你是说它返回代码> 357?/代码>?(你链接的第一页在底部回答了这个问题,在FAQ中.这个问题毫无意义。这就像问如何将“两个蘑菇”中的“二”转换为“两辆车”中的“二”。没什么可做的。在这种情况下,0x43b28000是二进制(十六进制)表示32位单字节。我没有代码,目前也没有时间,但如果我以后有一点时间,我将描述如何实现它(如果没有其他人这样做)。它只涉及一些移位和一些加法/减法。@roger_rowland:我觉得userXYZ想知道它是如何工作的,而不是让编译器替他做的。@Rudy Velthuis-好吧。我在OP的帖子中跟踪了链接,它描述了Java应用程序是如何工作的,这与“reinterpret_cast”的工作原理完全相同。是吗如果你使用C++,你可以使用RealTytCask.我不明白。你的函数返回一个浮点。它怎么能返回<代码> 0x43B2800< /代码>?你是说它返回代码> 357 < /代码>?(你链接的第一页在底部回答了这个问题,在FAQ中的第二个问题)这个问题毫无意义。这就像问如何将“两个蘑菇”中的“二”转换为“两辆车”中的“二”。没什么可做的。在这种情况下,0x43b28000是二进制(十六进制)表示32位单字节。我没有代码,目前也没有时间,但如果我以后有一点时间,我将描述如何实现它(如果没有其他人这样做)。它只涉及一些移位和一些加法/减法。@roger_rowland:我觉得userXYZ想知道它是如何工作的,而不是让编译器替他做的。@Rudy Velthuis-好吧。我在OP的帖子中找到了链接,它描述了Java应用程序是如何做到的,我也知道了