转换诠释为浮动/浮动使用按位到INT [英] Converting Int to Float/Float to Int using Bitwise

查看:244
本文介绍了转换诠释为浮动/浮动使用按位到INT的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在想,如果你能帮助解释上的整数浮动,或者浮点转换为整数的过程。对于我的课,我们要做到这一点只用位运算符,但我认为从型,将铸造一个坚定的认识将帮助我更多的这个阶段。

I was wondering if you could help explain the process on converting an integer to float, or a float to an integer. For my class, we are to do this using only bitwise operators, but I think a firm understanding on the casting from type to type will help me more in this stage.

据我所知,到目前为止,对于int浮动,你必须将整数转换成二进制,从那里浮动通过寻找尾数,指数和部分归整的值,然后输出的值?

From what I know so far, for int to float, you will have to convert the integer into binary, normalize the value of the integer by finding the significand, exponent, and fraction, and then output the value in float from there?

至于浮到整型,你将不得不价值分成尾数,指数和分数,然后扭转上述说明得到一个int值?

As for float to int, you will have to separate the value into the significand, exponent, and fraction, and then reverse the instructions above to get an int value?

我试图遵循这个问题的说明:铸造浮到INT(按位)用C

I tried to follow the instructions from this question: Casting float to int (bitwise) in C

不过,我是不是真的能够理解它。

But I was not really able to understand it.

另外,能不能有人解释为什么舍入将是必要的值不是转换INT当浮动23位更大?

Also, could someone explain why rounding will be necessary for values greater than 23 bits when converting int to float?

在此先感谢

推荐答案

首先,一纸你应该考虑的阅读,如果你想了解浮点弱点更好:什么每台计算机科学家应该知道关于浮点运算,< A HREF =htt​​p://www.validlab.com/goldberg/paper.pdf> http://www.validlab.com/goldberg/paper.pdf

First, a paper you should consider reading, if you want to understand floating point foibles better: "What Every Computer Scientist Should Know About Floating Point Arithmetic," http://www.validlab.com/goldberg/paper.pdf

和现在一些肉。

以下code是光秃秃的骨头,并试图以从范围为0℃的 unsigned int类型的IEEE-754单precision浮动;值&LT; 2 24 。这就是你最有可能在现代硬件上遇到的格式,这是你似乎你原来的问题,以引用格式。

The following code is bare bones, and attempts to produce an IEEE-754 single precision float from an unsigned int in the range 0 < value < 224. That's the format you're most likely to encounter on modern hardware, and it's the format you seem to reference in your original question.

IEEE-754单precision花车分为三个领域:一个符号位,指数的8位,尾数23位(有时也称为尾数)。 IEEE-754使用的隐藏1 的尾数,也就是说,尾数实际上是24位总数。该位被挤得左到右,并在第31位的符号位,指数在30位.. 23,和22位尾数0 ..从维基百科如下图所示:

IEEE-754 single-precision floats are divided into three fields: A single sign bit, 8 bits of exponent, and 23 bits of significand (sometimes called a mantissa). IEEE-754 uses a hidden 1 significand, meaning that the significand is actually 24 bits total. The bits are packed left to right, with the sign bit in bit 31, exponent in bits 30 .. 23, and the significand in bits 22 .. 0. The following diagram from Wikipedia illustrates:

浮点格式

的指数为127的偏压,这意味着与浮点数相关联的实际指数大于存储在指数字段中的值小于127。因此,0指数将连接codeD为127。

The exponent has a bias of 127, meaning that the actual exponent associated with the floating point number is 127 less than the value stored in the exponent field. An exponent of 0 therefore would be encoded as 127.

(注:满维基百科文章可以是有趣的,你参考:<一href=\"http://en.wikipedia.org/wiki/Single_$p$pcision_floating-point_format\">http://en.wikipedia.org/wiki/Single_$p$pcision_floating-point_format )

(Note: The full Wikipedia article may be interesting to you. Ref: http://en.wikipedia.org/wiki/Single_precision_floating-point_format )

因此​​,IEEE-754数为0x40000000是PTED间$ P $如下:

Therefore, the IEEE-754 number 0x40000000 is interpreted as follows:


  • 位31 = 0:正值

  • 位30 .. 23 = 0x80的:指数= 128 - 127 = 1(又名2 1

  • 22位1..0都是0:有效数字= 1.00000000_00000000_0000000。 (注意:我恢复了隐藏1)。

所以值为1.0×2 1 = 2.0。

So the value is 1.0 x 21 = 2.0.

要转换的 unsigned int类型在IEEE-754格式上面给出的话,要的东西有限的范围内,可以使用函数类似下面。它采用以下步骤:

To convert an unsigned int in the limited range given above, then, to something in IEEE-754 format, you might use a function like the one below. It takes the following steps:


  • 对齐领先整数1到​​的隐藏的1浮点再presentation。
  • 的位置
  • 虽然对准整数,记录取得移位的总数。

  • 面具掉隐藏1。

  • 使用制成移位数,计算指数,并将其追加到的数量。

  • 使用 reinter pret_cast ,转换生成的位模式为浮动。这部分是一个丑陋的黑客攻击,因为它使用一个类型punned指针。您还可以通过滥用一个联盟做到这一点。一些平台提供了一个内在的操作(如 _itof ),使这个rein​​ter pretation不太难看。

  • Aligns the leading 1 of the integer to the position of the hidden 1 in the floating point representation.
  • While aligning the integer, records the total number of shifts made.
  • Masks away the hidden 1.
  • Using the number of shifts made, computes the exponent and appends it to the number.
  • Using reinterpret_cast, converts the resulting bit-pattern to a float. This part is an ugly hack, because it uses a type-punned pointer. You could also do this by abusing a union. Some platforms provide an intrinsic operation (such as _itof) to make this reinterpretation less ugly.

有更快的方法来做到这一点;这一次,就是要教学上有用的,如果不是超级高效的:

There are much faster ways to do this; this one is meant to be pedagogically useful, if not super efficient:

float uint_to_float(unsigned int significand)
{
    // Only support 0 < significand < 1 << 24.
    if (significand == 0 || significand >= 1 << 24)
        return -1.0;  // or abort(); or whatever you'd like here.

    int shifts = 0;

    //  Align the leading 1 of the significand to the hidden-1 
    //  position.  Count the number of shifts required.
    while ((significand & (1 << 23)) == 0)
    {
        significand <<= 1;
        shifts++;
    }

    //  The number 1.0 has an exponent of 0, and would need to be
    //  shifted left 23 times.  The number 2.0, however, has an
    //  exponent of 1 and needs to be shifted left only 22 times.
    //  Therefore, the exponent should be (23 - shifts).  IEEE-754
    //  format requires a bias of 127, though, so the exponent field
    //  is given by the following expression:
    unsigned int exponent = 127 + 23 - shifts;

    //  Now merge significand and exponent.  Be sure to strip away
    //  the hidden 1 in the significand.
    unsigned int merged = (exponent << 23) | (significand & 0x7FFFFF);


    //  Reinterpret as a float and return.  This is an evil hack.
    return *reinterpret_cast< float* >( &merged );
}

您可以使用,在一些检测1领先的功能使这一过程更加高效。 (这有时像 CLZ 名去算前导零,或规范的正常化。)

You can make this process more efficient using functions that detect the leading 1 in a number. (These sometimes go by names like clz for "count leading zeros", or norm for "normalize".)

您还可以通过记录符号,取整数的绝对值,执行上述步骤,然后把符号变成数位31这个延伸到正负号。

You can also extend this to signed numbers by recording the sign, taking the absolute value of the integer, performing the steps above, and then putting the sign into bit 31 of the number.

有关整数> = 2 <燮> 24 ,整个整数不适合32位浮点格式的有效位字段。这就是为什么你需要圆:您为了让价值契合输位。因此,多个整数最终将映射到相同的浮点模式。确切的映射取决于舍入模式(圆朝-Inf,圆朝+天道酬勤,圆趋向于零,向最近的偶数)。但问题的事实是,你不能没有一定的损失推24位到少于24位。

For integers >= 224, the entire integer does not fit into the significand field of the 32-bit float format. This is why you need to "round": You lose LSBs in order to make the value fit. Thus, multiple integers will end up mapping to the same floating point pattern. The exact mapping depends on the rounding mode (round toward -Inf, round toward +Inf, round toward zero, round toward nearest even). But the fact of the matter is you can't shove 24 bits into fewer than 24 bits without some loss.

您可以在code以上方面看到这一点。它的工作原理对准领先1到隐藏1的位置。如果值> = 2 24 中,code将需要转移的右键的,不是的的,那一定是转移LSB的远。舍入模式只是告诉你如何处理位转移开来。

You can see this in terms of the code above. It works by aligning the leading 1 to the hidden 1 position. If a value was >= 224, the code would need to shift right, not left, and that necessarily shifts LSBs away. Rounding modes just tell you how to handle the bits shifted away.

这篇关于转换诠释为浮动/浮动使用按位到INT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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