假设一个低端微处理器没有浮点运算,我需要生成一个IEE754单精度浮点格式数来推送到文件。
我需要编写一个函数,它将三个整数作为符号,整数和分数,并返回一个字节数组,其中4个字节是IEEE 754单精度表示。
类似的东西:
// Convert 75.65 to 4 byte IEEE 754 single precision representation
char* float = convert(0, 75, 65);
有人有指针或示例C代码吗?我特别难以理解如何转换尾数。
答案 0 :(得分:1)
您需要生成符号(1位),指数(8位,偏置幂2)和分数/尾数(23位)。
请记住,该分数具有隐含的前导' 1'位,这意味着最重要的领先' 1' bit(2 ^ 22)未以IEEE格式存储。例如,给定一小部分0x755555(24位),存储的实际位将为0x355555(23位)。
还要记住,分数是移位的,这样二进制点就在隐式前导的右边,即1'位。因此IEEE 11位的11 0101 0101 ...代表24位二进制分数1.11 0101 0101 ...... 这意味着必须相应地调整指数。
答案 1 :(得分:0)
值是否必须写成大端或小端?反转位排序?
如果您有空,您应该考虑将该值写为字符串文字。这样你就可以轻松转换整数:只需编写int部分并将“e0”写为指数(或省略指数并写“.0”)。
对于二进制表示,您应该查看Wikipedia。最好是首先将位域组装为uint32_t
- 结构在链接文章中给出。请注意,如果整数值超过23位,则可能必须舍入。请记住规范化生成的值。
第二步是将uint32_t
序列化为uint8_t
- 数组。记住结果的结束!
如果您真的想要8位值,请注意使用uint8_t
作为结果;你应该使用无符号类型。对于中间表示,建议使用uint32_t
,因为这将保证您对32位值进行操作。
答案 2 :(得分:0)
你没有去过,所以没有放弃。
请记住,您可以将两个32位整数视为一个& b被解释为十进制a.b为单个64位整数,指数为2 ^ -32(其中^为指数)。
所以没有做任何事情你就得到了以下形式:
s * m * 2^e
唯一的问题是你的尾数太长而你的号码没有标准化。
通过可能的舍入步骤进行一些移位和加/减,你就完成了。
答案 3 :(得分:0)
基本前提是:
float
。whole
和派系部分hundredths
的二进制定点表示。此代码使用分别编码整数和百分之一字段的结构。重要的是whole
字段至少为32位。whole, hundredths
时不会产生非数字,因此不会生成float
个特殊情况。
#include <assert.h>
#include <stdint.h>
#define IMPLIED_BIT 0x00800000L
typedef struct {
int_least32_t whole;
int hundreth;
} x_xx;
int_least32_t covert(int whole, int hundreth) {
assert(whole >= 0 && hundreth >= 0 && hundreth < 100);
if (whole == 0 && hundreth == 0) return 0;
x_xx x = { whole, hundreth };
int_least32_t expo = 0;
int sticky_bit = 0; // Note any 1 bits shifted out
while (x.whole >= IMPLIED_BIT * 2) {
expo++;
sticky_bit |= x.hundreth % 2;
x.hundreth /= 2;
x.hundreth += (x.whole % 2)*(100/2);
x.whole /= 2;
}
while (x.whole < IMPLIED_BIT) {
expo--;
x.hundreth *= 2;
x.whole *= 2;
x.whole += x.hundreth / 100;
x.hundreth %= 100;
}
int32_t mantissa = x.whole;
// Round to nearest - ties to even
if (x.hundreth >= 100/2 && (x.hundreth > 100/2 || x.whole%2 || sticky_bit)) {
mantissa++;
}
if (mantissa >= (IMPLIED_BIT * 2)) {
mantissa /= 2;
expo++;
}
mantissa &= ~IMPLIED_BIT; // Toss MSbit as it is implied in final
expo += 24 + 126; // Bias: 24 bits + binary32 bias
expo <<= 23; // Offset
return expo | mantissa;
}
void test_covert(int whole, int hundreths) {
union {
uint32_t u32;
float f;
} u;
u.u32 = covert(whole, hundreths);
volatile float best = whole + hundreths / 100.0;
printf("%10d.%02d --> %15.6e %15.6e Same:%d\n", whole, hundreths, u.f, best,
best == u.f);
}
#include <limits.h>
int main(void) {
test_covert(75, 65);
test_covert(0, 1);
test_covert(INT_MAX, 99);
return 0;
}
输出
75.65 --> 7.565000e+01 7.565000e+01 Same:1
0.01 --> 1.000000e-02 1.000000e-02 Same:1
2147483647.99 --> 2.147484e+09 2.147484e+09 Same:1
已知问题:未应用签名。
答案 4 :(得分:0)