使用C中某些整数的位操作中断将整数转换为浮点数 [英] Cast Integer to Float using Bit Manipulation breaks on some integers in C

查看:103
本文介绍了使用C中某些整数的位操作中断将整数转换为浮点数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在进行类分配时,我试图仅使用位操作将整数转换为浮点数(仅限于任何整数/无符号操作,包括||,&&.我的代码适用于大多数值,但是某些值无法生成我想要的结果.

Working on a class assignment, I'm trying to cast an integer to a float only using bit manipulations (limited to any integer/unsigned operations incl. ||, &&. also if, while). My code is working for most values, but some values are not generating the results I'm looking for.

例如,如果x为0x807fffff,则得到0xceff0001,但正确的结果应为0xceff0000.我想我的尾数和舍入缺少了一些内容,但不能完全固定下来.我也在SO上查看了其他一些线程 how-to-manual

For example, if x is 0x807fffff, I get 0xceff0001, but the correct result should be 0xceff0000. I think I'm missing something with my mantissa and rounding, but can't quite pin it down. I've looked at some other threads on SO as well converting-int-to-float and how-to-manually

unsigned dl22(int x) {


    int tmin = 0x1 << 31;
    int tmax = ~tmin;

    unsigned signBit = 0;
    unsigned exponent;
    unsigned mantissa;
    int bias = 127;

    if (x == 0) {
        return 0;
    }

    if (x == tmin) {
        return 0xcf << 24;
    }

    if (x < 0) {
        signBit = x & tmin;
        x = (~x + 1);
    }


    exponent = bias + 31;

    while ( ( x & tmin) == 0 ) {
        exponent--;
        x <<= 1;
    }

    exponent <<= 23;
    int mantissaMask = ~(tmin >> 8);
    mantissa = (x >> 8) & mantissaMask;

    return (signBit | exponent | mantissa);
}

编辑/更新 找到了可行的解决方案-见下文

EDIT/UPDATE Found a viable solution - see below

推荐答案

您的代码为您提供的示例为我提供了预期的输出.但是,正如注释中所讨论的那样,从C的角度来看,它确实表现出不确定的行为-不仅在tmin的计算中,而且出于相同的原因,在计算指数的循环中也是如此.此代码无论在何种程度上都会因环境而异,这取决于未定义的行为或您对[unsigned] int的大小对于所使用的C实现而言不正确的假设.

Your code produces the expected output for me on the example you presented. As discussed in comments, however, from C's perspective it does exhibit undefined behavior -- not just in the computation of tmin, but also, for the same reason, in the loop wherein you compute the exponent. To whatever extent this code produces results that vary from environment to environment, that will follow either from the undefined behavior or from your assumption about the size of [unsigned] int being incorrect for the C implementation in use.

尽管如此,如果我们假设(不安全地)

Nevertheless, if we assume (unsafely)

  1. int的移位进行操作,就好像左操作数被重新解释为具有相同位模式的unsigned int,对其进行操作,并且将所得的位模式重新解释为int,并且
  2. intunsigned int的宽度至少为32位,
  1. that shifts of ints operate as if the left operand were reinterpreted as an unsigned int with the same bit pattern, operated upon, and the resulting bit pattern reinterpreted as an int, and
  2. that int and unsigned int are at least 32 bits wide,

那么您的代码似乎是正确的,取模取整.

then your code seems correct, modulo rounding.

如果输入int的绝对值具有超过24个有效二进制数字(即至少2 24 ),但是,转换中会损失一些精度. .在这种情况下,正确的结果将取决于您打算实现的FP舍入模式.舍入不正确的结果将在最后一个位置偏移1个单位;影响多少结果取决于取整模式.

In the event that the absolute value of the input int has more than 24 significant binary digits (i.e. it is at least 224), however, some precision will be lost in the conversion. In that case the correct result will depend on the FP rounding mode you intend to implement. An incorrectly rounded result will be off by 1 unit in the last place; how many results that affects depends on the rounding mode.

当您这样做时,简单地截断/移出多余的位会向零模式舍入.这是标准的舍入模式之一,但不是默认值.默认的舍入模式是四舍五入到最接近的可表示数字,为了解决结果具有最低有效位0(舍入到偶数)的问题,对并进行了解析.还有其他三种标准模式.要实现除零舍入以外的任何模式,您需要在缩放后和移开有效位之前捕获有效位数的8个最低有效位.这些以及其他详细信息(取决于所选的舍入模式)将决定如何应用正确的舍入.

Simply truncating / shifting off the extra bits as you do yields round toward zero mode. That's one of the standard rounding modes, but not the default. The default rounding mode is to round to the nearest representable number, with ties being resolved in favor of the result having least-significant bit 0 (round to even); there are also three other standard modes. To implement any mode other than round-toward-zero, you'll need to capture the 8 least-significant bits of the significand after scaling and before shifting them off. These, together with other details depending on the chosen rounding mode, will determine how to apply the correct rounding.

在32位二进制补码中,大约有一半的舍入方式在舍入到零模式下转换时与在其他任何一种模式下转换时舍入方式不同; 哪些数字存在差异取决于您考虑的舍入模式.

About half of the 32-bit two's complement numbers will be rounded differently when converted in round-to-zero mode than when converted in any one of the other modes; which numbers exhibit a discrepancy depends on which rounding mode you consider.

这篇关于使用C中某些整数的位操作中断将整数转换为浮点数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆