簡體   English   中英

將int轉換為float時在后台會發生什么

[英]what happens at background when convert int to float

我有一些不明白如何逐步將int轉換為float? 假設我有一個二進制格式的帶符號整數。 而且,我想把它用手漂浮。 但是,我不能。 因此,CAn一個人告訴我如何逐步進行轉換?

我在c中進行多次轉換? 喜歡;

  int a = foo ( );
  float f = ( float ) a ;

但是,我還沒弄清楚背景會發生什么。 而且,為了更好地理解,我想手工完成轉換。

編輯:如果你對轉換了解很多,你也可以提供有關浮動到雙轉換的信息。 而且,對於float到int

浮點值(IEEE754,無論如何)基本上有三個組成部分:

  • 標志s ;
  • 一系列指數位e ;
  • 一系列尾數位m

精度決定了指數和尾數有多少位可用。 讓我們檢查單精度浮點的值0.1:

s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm    1/n
0 01111011 10011001100110011001101
           ||||||||||||||||||||||+- 8388608
           |||||||||||||||||||||+-- 4194304
           ||||||||||||||||||||+--- 2097152
           |||||||||||||||||||+---- 1048576
           ||||||||||||||||||+-----  524288
           |||||||||||||||||+------  262144
           ||||||||||||||||+-------  131072
           |||||||||||||||+--------   65536
           ||||||||||||||+---------   32768
           |||||||||||||+----------   16384
           ||||||||||||+-----------    8192
           |||||||||||+------------    4096
           ||||||||||+-------------    2048
           |||||||||+--------------    1024
           ||||||||+---------------     512
           |||||||+----------------     256
           ||||||+-----------------     128
           |||||+------------------      64
           ||||+-------------------      32
           |||+--------------------      16
           ||+---------------------       8
           |+----------------------       4
           +-----------------------       2

標志是積極的,這很容易。

指數為64+32+16+8+2+1 = 123 - 127 bias = -4 ,因此乘數為2 -41/16 偏見是存在的,這樣你就可以獲得非常小的數字(如10 -30 )以及大數字。

尾數很粗糙。 它由1 (隱式基數)加上(對於所有這些位,每個值為1 /(2 n ),因為n1開始並向右增加), {1/2, 1/16, 1/32, 1/256, 1/512, 1/4096, 1/8192, 1/65536, 1/131072, 1/1048576, 1/2097152, 1/8388608}

當你添加所有這些,你得到1.60000002384185791015625

當你乘以2 -4乘數時,得到0.100000001490116119384765625 ,這就是為什么他們說你不能完全代表0.1作為IEEE754浮點數。

整數轉換為浮點數方面,如果尾數中包含盡可能多的位(包括隱式1),則只需傳輸整數位模式並選擇正確的指數即可。 不會有精度損失。 例如,雙精度IEEE754(64位,其中52/53為尾數)對32位整數沒有任何問題。

如果整數中有更多位(例如32位整數和32位單精度浮點數,只有23/24位尾數),則需要縮放整數。

這涉及剝離最低有效位(實際舍入),以使其適合尾數位。 這當然會導致精度損失,但這是不可避免的。


我們來看看具體的值123456789 以下程序轉儲每種數據類型的位。

#include <stdio.h>

static void dumpBits (char *desc, unsigned char *addr, size_t sz) {
    unsigned char mask;
    printf ("%s:\n  ", desc);
    while (sz-- != 0) {
        putchar (' ');
        for (mask = 0x80; mask > 0; mask >>= 1, addr++)
            if (((addr[sz]) & mask) == 0)
                putchar ('0');
            else
                putchar ('1');
    }
    putchar ('\n');
}

int main (void) {
    int intNum = 123456789;
    float fltNum = intNum;
    double dblNum = intNum;

    printf ("%d %f %f\n",intNum, fltNum, dblNum);
    dumpBits ("Integer", (unsigned char *)(&intNum), sizeof (int));
    dumpBits ("Float", (unsigned char *)(&fltNum), sizeof (float));
    dumpBits ("Double", (unsigned char *)(&dblNum), sizeof (double));

    return 0;
}

我系統的輸出如下:

123456789 123456792.000000 123456789.000000
integer:
   00000111 01011011 11001101 00010101
float:
   01001100 11101011 01111001 10100011
double:
   01000001 10011101 01101111 00110100 01010100 00000000 00000000 00000000

我們將一次看一下這些。 首先是整數,簡單的兩個冪:

   00000111 01011011 11001101 00010101
        |||  | || || ||  || |    | | +->          1
        |||  | || || ||  || |    | +--->          4
        |||  | || || ||  || |    +----->         16
        |||  | || || ||  || +---------->        256
        |||  | || || ||  |+------------>       1024
        |||  | || || ||  +------------->       2048
        |||  | || || |+---------------->      16384
        |||  | || || +----------------->      32768
        |||  | || |+------------------->      65536
        |||  | || +-------------------->     131072
        |||  | |+---------------------->     524288
        |||  | +----------------------->    1048576
        |||  +------------------------->    4194304
        ||+---------------------------->   16777216
        |+----------------------------->   33554432
        +------------------------------>   67108864
                                         ==========
                                          123456789

現在讓我們看一下單精度浮點數。 注意尾數匹配整數的位模式為近似完美匹配:

mantissa:       11 01011011 11001101 00011    (spaced out).
integer:  00000111 01011011 11001101 00010101 (untouched).

在尾數的左邊有一個隱含的 1位,它也在另一端被舍入,這是精度損失的來源(值從123456789變為123456792就像上面程序的輸出一樣)。

制定價值觀:

s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm    1/n
0 10011001 11010110111100110100011
           || | || ||||  || |   |+- 8388608
           || | || ||||  || |   +-- 4194304
           || | || ||||  || +------  262144
           || | || ||||  |+--------   65536
           || | || ||||  +---------   32768
           || | || |||+------------    4096
           || | || ||+-------------    2048
           || | || |+--------------    1024
           || | || +---------------     512
           || | |+-----------------     128
           || | +------------------      64
           || +--------------------      16
           |+----------------------       4
           +-----------------------       2

標志是積極的。 指數為128+16+8+1 = 153 - 127 bias = 26 ,因此乘數為2 2667108864

尾數是1 (隱式基數)加(如上所述), {1/2, 1/4, 1/16, 1/64, 1/128, 1/512, 1/1024, 1/2048, 1/4096, 1/32768, 1/65536, 1/262144, 1/4194304, 1/8388608} 當你添加所有這些,你得到1.83964955806732177734375

當你乘以2 26乘數時,得到123456792 ,與程序輸出相同。

雙位掩碼輸出是:

s eeeeeeeeeee mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
0 10000011001 1101011011110011010001010100000000000000000000000000

打算通過找出那個野獸的價值的過程:-)但是,我在整數格式旁邊顯示尾數以顯示公共位表示:

mantissa:       11 01011011 11001101 00010101 000...000 (spaced out).
integer:  00000111 01011011 11001101 00010101           (untouched).

您可以再次看到左側隱含位的共性和右側的更大位可用性,這就是為什么在這種情況下不會丟失精度的原因。


在浮點數和雙打數之間的轉換方面,這也很容易理解。

首先必須檢查特殊值,如NaN和無窮大。 這些由特殊的指數/尾數組合表示,並且可能更容易檢測到這些前置角度,以新格式生成等效物。

那么在你從double到float的情況下,你顯然可用的范圍較小,因為指數中的位數較少。 如果你的雙精度超出浮動范圍,你需要處理它。

假設它適合,那么你需要:

  • 重新指數(這兩種類型的偏差是不同的)。
  • 從尾數中復制盡可能多的位(如果需要,可以舍入)。
  • 用零位填充剩余的目標尾數(如果有的話)。

從概念上講,這很簡單。 float (在IEEE 754-1985中)具有以下表示:

  • 1位符號
  • 8位指數(0表示非規范化數字,1表示-126,127表示0,255表示無窮大)
  • 23位尾數(“1.”后面的部分)

所以基本上它大致是:

  • 確定數字的符號和大小
  • 找到24個最有效位,正確舍入
  • 調整指數
  • 將這三個部分編碼為32位形式

在實現您自己的轉換時,它很容易測試,因為您只需將結果與內置類型轉換運算符進行比較。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM