91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

float 和 double (我內存里的浮點型數據?)

發布時間:2020-08-10 20:16:38 來源:ITPUB博客 閱讀:153 作者:LinuxDevqqqqqq 欄目:編程語言

二更,因為好幾個人因為這篇文章把我批斗了,把有問題的地方修正。

今天看到一個問題

能不能用 double 去取代 float

前段時間,有個朋友問我,在 java 里面我想把一個高精度的浮點型存儲下來,但是每次存儲的時候都會被強制降低精度,對于浮點型的理解,真的非常非常重要,特別對嵌入式軟件開發,或者算法開發,涉及到數據類的,浮點型非常非常關鍵,就比如,微信為什么不讓我發 0.0000000001 元的微信紅包呢? 有沒有想過這個問題?如果這樣做對于他們服務器后臺的運算能力要求非常高, so ~~~~~

所以想簡單寫一下, float double 的區別以及應用場景

<img src="https://pic3.zhimg.com/v2-19c15ba72548ffb535861e5a5625b65a_b.jpg" data-caption="" data-size="normal" data-rawwidth="281" data-rawheight="25" class="content_image" width="281">

float 和 double (我內存里的浮點型數據?)

1 、浮點型的值范圍

float double 的范圍是由指數的位數來決定的。在 VC++6.0 中, float 4 個字節, double 8 個字節。

Type Storage size Value range 

float 4 byte 1.2E-38 to 3.4E+38

double 8 byte 2.3E-308 to 1.7E+308

long double 10 byte 3.4E-4932 to 1.1E+4932


2 、浮點型在內存里面是如何存儲的?

我相信這個問題大家沒有好好的去考慮過,浮點型如何存儲,這才是我們討論浮點型的關鍵所在,關于上面的浮點型取值范圍,也是網上拷貝下來的,至于真實性,我覺得你們要看了這部分才可能真正理解浮點型,而且最好在自己的編譯器去測試,浮點型是可以等于負數的,所以上面的范圍,你們認為是正確的嗎?

<img src="https://pic2.zhimg.com/v2-9d554740d41074c27e49febf5448c86d_b.jpg" data-caption="" data-size="normal" data-rawwidth="300" data-rawheight="300" class="content_image" width="300">

float 和 double (我內存里的浮點型數據?)

我拿 float 來舉個栗子:

<img src="https://pic4.zhimg.com/v2-8a912b5c1343b1223ea36b94538dd67f_b.jpg" data-size="normal" data-rawwidth="637" data-rawheight="191" class="origin_image zh-lightbox-thumb" width="637" data-original="https://pic4.zhimg.com/v2-8a912b5c1343b1223ea36b94538dd67f_r.jpg">

float 和 double (我內存里的浮點型數據?)

float 在內存中的存儲方式

以下 部分如發現問題,請留言,會發小小紅包感謝,微信 weiqifa0

首先使用基數 2 而不是基數 10 來表示科學計數法變體中的浮點值。例如,值 3.14159 可以表示為

1.570795 * 2^{1}


1.570795 有效數字又名尾數(在上圖中指尾數部分) ; 它是包含有效數字的數字的一部分。此值乘以基數 2 ,上升到 1 的冪,得到 3.14159

浮點數通過存儲 有效數和指數(以及符號位) 進行編碼。

典型的 32 位布局如下所示:

 3 32222222 22211111111110000000000

 1 09876543 21098765432109876543210

+-+--------+-----------------------+

| |        |                       |

+-+--------+-----------------------+

 ^    ^                ^

 |    |                |

 |    |                +-- 有效數  

 |    |

 |    +------------------- 指數

 |

 +------------------------ 符號位

與有符號整數類型一樣,高位表示符號 ; 表示 值, 1 表示 值。

而對于指數部分,因為指數可正可負, 8 位的指數位能表示的指數范圍就應該為 :-127-128 了, 所以指數部分的存儲采用移位存儲, 存儲的數據為元數據 +127

舉例:

<img src="https://pic1.zhimg.com/v2-0df447013f853a47b89d51dd0d88a288_b.jpg" data-caption="" data-size="normal" data-rawwidth="191" data-rawheight="98" class="content_image" width="191">

float 和 double (我內存里的浮點型數據?)

剩余的比特用于有效數字。每個位表示從左側算起的 2 的負冪, float 一共 23 ,舉例:

<img src="https://pic2.zhimg.com/v2-f5a935ed3397d4b35c3592e0059f492d_b.jpg" data-caption="" data-size="normal" data-rawwidth="625" data-rawheight="81" class="origin_image zh-lightbox-thumb" width="625" data-original="https://pic2.zhimg.com/v2-f5a935ed3397d4b35c3592e0059f492d_r.jpg">

float 和 double (我內存里的浮點型數據?)

某些平臺假定有效數中的 隱藏 前導位始終設置為 1 ,因此有效數中的值始終在 [0.5,1 之間 ] 。這允許這些平臺以稍高的精度存儲值。

所以 3.14159 的值將表示為

    0 10000000 10010010000111111010000

    ^ ^        ^

    | |        |

    | |        + --- 有效數 = 1.570795 ...

    | |

    | + ------------------- 指數 = 2 130  -  128

    |

    + ------------------------- sign = 0 (正面)


    value = 1 (符號位) * 2 (指數位) * (有效數字)

    = 1 0 * 2^1 * 1.570795 ...

    = 3.14159 ......

現在,如果你將有效數字中的所有位相加,你會注意到它們總共 不是 3.14195 ;

他們實際上 3.141590118408203125 ,(小編實測數據)

沒有足夠的位來準確存儲值 ; 我們只能存儲一個近似值。有效數字中的位數決定了精度 23 位給出了大約 6 位精度的十進制數字 64 位浮點類型在有效位數中提供足夠的位, 可提供大約 12 15 位的精度 。但要注意,有一些數值不能被精確表示。就像 1/3 這樣的值不能用有限數量的十進制數字表示,由于值是近似值,因此使用它們進行計算也是近似值,并且累積誤差會累積。

<img src="https://pic2.zhimg.com/v2-9d554740d41074c27e49febf5448c86d_b.jpg" data-caption="" data-size="normal" data-rawwidth="300" data-rawheight="300" class="content_image" width="300">

float 和 double (我內存里的浮點型數據?)

#include <stdio.h>


void main ( void )

{

    for ( float i = ; i < 1 ;i += 0.01 )

    {

        printf( "%f \r\n" ,i);

    }

    for ( double i = ; i < 1 ;i += 0.01 )

    {

        printf( "%f\r\n" ,i);

    }

    for ( long double i = ; i < 1 ;i += 0.01 )

    {

        printf( "%Lf\r\n" ,i);

    }

}

注意其中輸出

<img src="https://pic2.zhimg.com/v2-6a46dbbc43ef82e569ea483166516b61_b.jpg" data-size="normal" data-rawwidth="161" data-rawheight="238" class="content_image" width="161">

float 和 double (我內存里的浮點型數據?)

0.830000 之后明顯出現了誤差

<img src="https://pic3.zhimg.com/v2-19c15ba72548ffb535861e5a5625b65a_b.jpg" data-caption="" data-size="normal" data-rawwidth="281" data-rawheight="25" class="content_image" width="281">

float 和 double (我內存里的浮點型數據?)

3 、反向驗證第二點的存儲推斷

上面的計算,我們可以通過一個小代碼反向驗證,代碼如下

#include <stdio.h>


int main ()

{

    /*0b1000000010010010000111111010000*/

    float num = 3.14159f ;

    int * p = ( int * ) & num;

    printf( "0x%x\n" , * p);

    return ;

}

<img src="https://pic3.zhimg.com/v2-74b26980679454ee8f3862b9fa9813d6_b.jpg" data-size="normal" data-rawwidth="617" data-rawheight="40" class="origin_image zh-lightbox-thumb" width="617" data-original="https://pic3.zhimg.com/v2-74b26980679454ee8f3862b9fa9813d6_r.jpg">

float 和 double (我內存里的浮點型數據?)

輸出 16 進制數據

so~~~~

3.14159 0x40490fd0 = 0 10000000 10010010000111111010000

<img src="https://pic4.zhimg.com/v2-4bda4f506f20dbb3baa4096af2d960a7_b.jpg" data-size="normal" data-rawwidth="573" data-rawheight="230" class="origin_image zh-lightbox-thumb" width="573" data-original="https://pic4.zhimg.com/v2-4bda4f506f20dbb3baa4096af2d960a7_r.jpg">

float 和 double (我內存里的浮點型數據?)

16 進制對應二進制數據

對于 double long double 的大小和精度可以通過這個方式來驗證。

<img src="https://pic3.zhimg.com/v2-19c15ba72548ffb535861e5a5625b65a_b.jpg" data-caption="" data-size="normal" data-rawwidth="281" data-rawheight="25" class="content_image" width="281">

float 和 double (我內存里的浮點型數據?)

4 、浮點型 printf 輸出格式

printf 輸出范圍 %f %g %Lf %e

#include <stdio.h>


void main ( void )

{

    float f_sum = ;

    double d_test = ;

    

    f_sum = - 3.4 * 10e-38 ;

    d_test = - 1.7 * 10e-308 ;


    printf( "%.38f\r\n" ,f_sum);

    printf( "%.308f\r\n" ,d_test);

    printf( "%g\r\n" ,f_sum);

    printf( "%g\r\n" ,d_test);

    

    f_sum = 3.4 * 10e37 ;

    d_test = 1.7 * 10e307 ;


    printf( "%g\r\n" ,f_sum);

    printf( "%g\r\n" ,d_test);

}

輸出如下

weiqifa@ubuntu:~/c/float$ gcc float.c && a.out

-0.00000000000000000000000000000000000034

-0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017

-3.4e-37

-1.7e-307

3.4e+38

1.7e+308

weiqifa@ubuntu:~/c/float$

<img src="https://pic3.zhimg.com/v2-19c15ba72548ffb535861e5a5625b65a_b.jpg" data-caption="" data-size="normal" data-rawwidth="281" data-rawheight="25" class="content_image" width="281">

float 和 double (我內存里的浮點型數據?)

5 精度問題

浮點數在內存中是按科學計數法來存儲的,其整數部分始終是一個隱含著的 "1" ,由于它是不變的,故不能對精度造成影響。

float 2^23 = 8388608 ,一共七位,這意味著最多能有 7 位有效數字,但絕對能保證的為 6 位,也即 float 的精度為 6~7 位有效數字;

double 2^52 = 4503599627370496 ,一共 16 位,同理, double 的精度為 15~16 位。

<img src="https://pic2.zhimg.com/v2-9d554740d41074c27e49febf5448c86d_b.jpg" data-caption="" data-size="normal" data-rawwidth="300" data-rawheight="300" class="content_image" width="300">

float 和 double (我內存里的浮點型數據?)

小代碼舉例

#include "stdio.h"


int main ( void )

    float fa = 1.0f

    float fb = - 2.123456789f

    float fc = 3.999999f

    double da = 1.0

    double db = - 4.0000000

    double dc = 3.123456789012345


    printf( "%-32.32f \r\n%-32.32f \r\n%-32.32f\r\n" ,fa,fb,fc);

    printf( "%-64.64f \r\n%-64.64f \r\n%-64.64f\r\n" ,da,db,dc);

    return

輸出

1.00000000000000000000000000000000 

-2.12345671653747558593750000000000 

3.99999904632568359375000000000000

1.0000000000000000000000000000000000000000000000000000000000000000 

-4.0000000000000000000000000000000000000000000000000000000000000000 

3.1234567890123448030692543397890403866767883300781250000000000000

<img src="https://pic3.zhimg.com/v2-19c15ba72548ffb535861e5a5625b65a_b.jpg" data-caption="" data-size="normal" data-rawwidth="281" data-rawheight="25" class="content_image" width="281">

float 和 double (我內存里的浮點型數據?)

6 、浮點值和 “0”

不知道大家對精度是怎么看的,理論上浮點是永遠不可能等于 “0” 的,只能無盡接近于 “0” ,所以你拿浮點型 “0” 比較 ,千萬千萬不要用 “== ” 恒等于符號,而是用大小于符號,精度越大,說明越無盡接近于 “0” ,有時候 float 的精度容易引起問題,看下面的例子。 --- 之前寫的,下面論證是否正確

評論已經有人說,浮點值肯定可以等于 1 ,這個不再做論證,現在論證浮點值和 值,是不是相等的。

所以,我做了實驗,我的文章不一定保證正確,但是提出的觀點一定要有論證的根據

晚上回來很累,跟楠哥睡了一下, 10 點的時候,楠哥又起來了,我也想更新下評論的問題,我測試的代碼如下,里面有注釋。

#include "stdio.h"


int main()

{

        /*0b01000000010010010000111111010000  3.14159 的二進制 */

/*0b00111111100000000000000000000000  1 的二進制 */

//int it = 0b01000000010010010000111111010000;

int it = 0b00111111100000000000000000000000;

        float *num = (float*)&it;

float num1;

int *p = (int *)&num1;

printf("%f\r\n",*num);/* 輸出我們認為是 0 的二進制數值 */

printf("%f\r\n",num1);/* 未初始化的 float */

printf("0x%x\r\n",*p);/* 打印里面的內容 */

/* 里面的內容是 0x401980 */

/* 轉成 二進制是 0b 0100 0000 0001 1001 1000 0000*/

/* 這樣好看點 0b 0 10000000 001100110000000*/

int it2 = 0x401980;

float *num3 = (float *)&it2;

/* 分別用三種方式輸出 */

printf("%f\r\n",*num3);

printf("%-32.32f\r\n",*num3);

printf("%d\r\n",(int)*num3);

    return 0;

}

輸出如下圖

<img src="https://pic1.zhimg.com/v2-92a07e5e1560c1cca7236f150b099918_b.jpg" data-caption="" data-size="normal" data-rawwidth="552" data-rawheight="168" class="origin_image zh-lightbox-thumb" width="552" data-original="https://pic1.zhimg.com/v2-92a07e5e1560c1cca7236f150b099918_r.jpg">

float 和 double (我內存里的浮點型數據?)

<img src="https://pic3.zhimg.com/v2-19c15ba72548ffb535861e5a5625b65a_b.jpg" data-caption="" data-size="normal" data-rawwidth="281" data-rawheight="25" class="content_image" width="281">

float 和 double (我內存里的浮點型數據?)

7 、總結

1 、浮點型在內存里面的存儲方式

2 、浮點型的精度問題

3 、浮點型的

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

长顺县| 海晏县| 商都县| 青海省| 镇江市| 庆城县| 古蔺县| 梁平县| 南岸区| 寻乌县| 历史| 开阳县| 济宁市| 怀仁县| 周宁县| 顺平县| 綦江县| 加查县| 巴林左旗| 万宁市| 石泉县| 务川| 达拉特旗| 清徐县| 滦南县| 遵化市| 深泽县| 芮城县| 沁水县| 紫阳县| 绥宁县| 龙海市| 保亭| 广河县| 信丰县| 黄山市| 德清县| 承德县| 张家界市| 蒙城县| 类乌齐县|