【问题标题】:convert int64 to float32 in c在c中将int64转换为float32
【发布时间】:2013-02-04 16:12:44
【问题描述】:

我从一个嵌入式设备中读取四个 16 位寄存器,它们代表一个 64 位整数。 read 函数在 uint16_t 中读取它们,我想将其转换为 float 32。如果我像这样进行转换,我会收到警告 left shift count >= width of type [默认启用]。

uint16_t u1,u2,u3,u4;
u1=readregister();
u2=readregister();
u3=readregister();
u4=readregister();

float num11 = (float) (u1 << 48);       
float num22 = (float) (u2 << 32); 
float num33 = (float) (u3 << 16);   
float num44 = (float) u4;   
float numm= num11+num22+num33+num44;
printf("%f\n", numm);

准确性如何?

【问题讨论】:

    标签: c floating-point int type-conversion


    【解决方案1】:

    这样做:

    float num11 = (uint64_t) u1 << 48;
    /* ... */
    

    如果编译器由于uint64_t 转换为float 而发出警告(C 不需要),您可以添加额外的float 转换:

    float num11 = (float) ((uint64_t) u1 << 48);
    

    这将消除警告。

    出于效率和精度的原因,最好先将您的 4 个uint16_t 转换为单个uint64_t,然后执行从uint64_tfloat 的单个转换。

    【讨论】:

    • 我不确定效率,但是构建一个精确的uint64_t 然后转换为浮点数绝对是最精确的,例如u4 == 1u2 &lt;&lt; 32 + u3 &lt;&lt; 16 正好在两个可表示@ 的中间987654333@s.
    • 关于效率,问题提到了嵌入式设备。如果没有 FPU,所有浮点运算都是在软件中完成的,并且需要大量的 CPU 周期。单个运行时整数到float 的转换肯定比四个好。
    • 对。我在考虑那种具有 FPU 但没有本机 64 位整数类型的嵌入式设备。 :)
    【解决方案2】:

    一种方法是:

    #include <math.h>
    
    float numm = (float) u4 + ldexpf(u3, 16) + ldexpf(u2, 32) + ldexpf(u1, 48);
    

    这并不要求您的嵌入式编译器提供除 uint16_t 之外的任何其他整数大小,它只需要 ldexpf()

    这会计算一个float,它在移位整数u1、...、u4 的数学和的一个ULP 内。

    【讨论】:

    • 这会导致多次舍入,并不总是产生正确的舍入结果。
    • @EricPostpischil 这是对的,因此我声明计算出的 float 在数学和的一个 ULP 范围内。
    • @EricPostpischil 有一种方法可以做到这一点,涉及到“粘性位”的想法,但在我的时区现在挖掘它为时已晚。
    • 粘位法将要舍入的位分为四种情况:“0 全零”、“0 非全零”、“1 全零”和“1 非-全零”,并利用这些以与“00”、“01”、“10”和“11”相同的方式四舍五入的事实。因此,为了确定舍入,只需要舍入第一位和其余位的 OR。但是,这需要确定要舍入哪些位,这需要找到最高位集并从那里向下计数 24 位。
    • 顺便说一句,你不需要 ldexpf()。你可以乘以例如65536.0f, 4294967296.0f, 281474976710656.0f.
    猜你喜欢
    • 2011-05-02
    • 2016-07-06
    • 1970-01-01
    • 2020-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-04
    相关资源
    最近更新 更多