我想知道是否有人可以让我在正确的方向上解决我正在处理的问题。我试图只使用ARM程序集和位操作执行以下C函数:
int float2int(float x) {
return (int) x;
}
我已经编写了这个(int2float)的反面而没有太多问题。我只是不确定从这个新问题的起点。
例如:
3 (int) = 0x40400000 (float)
0011 = 0 10000000 10000000000000000000000
其中0是符号位,10000000是指数,10000000000000000000000是尾数/分数。
有人可以简单地指出我正确的方向吗?即使是C伪代码表示也会有所帮助。我知道我需要提取符号位,提取指数并反转偏差(127)并提取分数但我不知道从哪里开始。
还有一个问题,即浮点数不能表示为整数(因为它溢出或是NaN)。
任何帮助将不胜感激!
答案 0 :(得分:1)
// Assume int can hold all the precision of a float.
int float2int(float x) {
int Sign = f_SignRawBit(x);
unsigned Mantissa = f_RawMantissaBits(x); // 0 - 0x7FFFFF
int Expo = f_RawExpoBits(x); // 0 - 255
// Form correct exponent and mantissa
if (Expo == EXPO_MAX) {
Handle_NAN_INF();
}
else if (Expo == EXPO_MIN) {
Expo += BIAS + 1 - MantissaOffset /* 23 */;
}
else {
Expo += BIAS - MantissaOffset /* 23 */;
Mantissa |= ImpliedBit;
}
while (Expo > 0) {
Expo--;
// Add code to detect overflow
Mantissa *= 2;
}
while (Expo < 0) {
Expo++;
// Add code to note last shifted out bit
// Add code to note if any non-zero bit shifted out
Mantissa /= 2;
}
// Add rounding code depending on `last shifted out bit` and `non-zero bit shifted out`. May not be need if rounding toward 0.
// Add code to detect over/under flow in the following
if (Sign) {
return -Mantissa;
}
return Mantissa;
}
答案 1 :(得分:1)
从一个数字开始,其尾数是您的数字(在您的示例中为00000011
),其指数为01111111
(127
,这是0存储在超过127的数字)
计算从LSb到最后设置位(未包括)的位数。对于计算的每个位,将1加到指数中。
在您的示例中:从LSb到最后一个(最高有效)位集只有一位,因此指数加1,结果为128(10000000
)。
左移你的尾数(原始数字),使最左边的设置位丢失。考虑到必须使用能够保持至少23位的变量来执行移位。因此,在您的示例中,原始尾数为00000000000000000000011
。你必须向左移动直到最左边的'1'丢失,导致10000000000000000000000
关于标志,如果原始数字是2补码,只需拿MSb,这将是你的标志。在您的示例中,0(正)
所以你的结果将是:
Sign : 0
Exponent: 10000000
Mantissa: 10000000000000000000000
另一个例子:将短整数-234
转换为浮点数。
使用2补码的-234
存储为1111111100010110
(16位)
从这里可以轻松获得标志:1(MSb)
我们必须使用绝对幅度,所以我们补充数字以得到正(幅度)版本。我们可以通过使用1111111111111111
对其进行评分,然后添加1.这样就可以了解0000000011101010
(234)
初始尾数(使用23位):00000000000000011101010
初始指数:01111111
(127)
计算从LSb到最左侧设置位的位数,不包括它。有7位。我们将此添加到我们的指数中:127+7=134 = 10000110
尾数向左移动,直到最左侧的设置位消失。这给了我们:
11010100000000000000000
我们的号码是:1 10000110 11010100000000000000000
答案 2 :(得分:1)
以下是一些用于转换的基本C ++代码。
#include <stdint.h>
union IntFloat
{
uint32_t i;
float f;
};
int32_t Float32ToInt24( const float & x )
{
IntFloat n;
n.f = x;
uint8_t negative = ((n.i >> 31) & 0x1 ) ; // 0x10000000
uint8_t exponent = ((n.i >> 23) & 0xFF ) ; // 0x7F800000
uint32_t mantissa = ((n.i >> 0) & 0x7FFFFF) | 0x800000 ; // 0x007FFFFF implicit bit
int32_t i = mantissa >> (22 - (exponent - 0x80));
if( !exponent )
return 0;
if( negative )
return -i;
else
return i;
}
注意:浮点数大于2 ^ 24将无法正确转换为整数,因为尾数只有24位精度。即添加两个浮点数16777216.0 + 1.0将无效!