在这篇博客中介绍了 float数据的二进制编码格式,因此我们可以自己写代码实现将一个长整型转换为 32位浮点数的功能。
下面是 long转 float的 C语言实现:
#include <stdio.h>
unsigned int count_leading_zero(unsigned long u)
{
unsigned int n = 0;
while (((u << n) & (1UL << 63)) == 0)
n++;
return n;
}
float ulong_to_float(unsigned long u)
{
unsigned int lz = count_leading_zero(u);
// 计算 float 指数部分的值,为(实际值 + 127),其中 127 为偏移,参见浮点数的二进制表示方法
unsigned int e = (u != 0) ? 127U + 63U - lz : 0;
// 将 float 尾数部分的值保存进变量 u
u = (u << lz) & 0x7fffffffffffffffUL;
// float 尾数部分只有 23 位,将 23 位以后的尾数部分保存进变量 t
unsigned long t = u & 0xffffffffffUL;
// 将 float 指数部分和尾数部分拼接在一起
unsigned int v = (e << 23) | (unsigned int)(u >> 40);
// 处理尾数部分的舍入逻辑:
// 若第 24 位尾数为 1,且第 24 位尾数后的值不为 0,则第 23 位尾数 + 1
// 若第 24 位尾数为 1,且第 24 位尾数后的值为 0,则判断第 23 位尾数是否为 1,若为 1,则第 23 位尾数 + 1
unsigned int r = t > 0x8000000000UL ? 1U : (t == 0x8000000000UL ? v & 1U : 0U);
unsigned int ret = v + r;
// 将拼接后得到的二进制按照浮点数返回
return *(float*)&ret;
}
float long_to_float(long l)
{
long s = l >> 63;
float r = ulong_to_float((l + s) ^ s);
return s ? -r : r;
}
int main(void)
{
long a = -123456789;
printf("a = %f\n", long_to_float(a));
printf("a = %f\n", (float)a);
return 0;
}
程序运行结果如下所示:
$ gcc main.c -o main
$ ./main
a = -123456792.000000
a = -123456792.000000
9304

被折叠的 条评论
为什么被折叠?



