網站首頁 編程語言 正文
浮點數的儲存格式
初步了解
首先讓我們通過一段代碼來認識一下浮點型和整型的區別:
int main()
{
int n = 9;//將整型9存儲到n中
float* pFloat = (float*)&n;
printf("n的值為:%d\n", n);
printf("*pFloat的值為:%f\n", *pFloat);
*pFloat = 9.0;//將浮點型9.0存儲到*pFloat中
printf("num的值為:%d\n", n);
printf("*pFloat的值為:%f\n", *pFloat);
return 0;
}
從代碼中我們可以看到,n和*pFloat指向的其實是同一塊區域,因為int和float都是4個字節的數據類型。讓我們來看看最后的輸出結果:
我們可以看到結果還是有些出人意料——
以整形儲存(n = 9),可以用整型正常讀取,但用浮點型讀取就會出現難以預料的情況 ;
同樣的,以浮點型存儲(*pFloat = 9.0),可以用浮點型正常讀取,但是用整型就會出現難以預料的情況。
從這個例子中我們可以知道,浮點型和整型的存儲和讀取方式是完全不同的。
深入探究
從前面的博客中,我們了解到了整型是通過補碼的形式儲存的,那么浮點型的儲存形式是什么樣的呢?
實際上,根據國際標準IEEE(電氣和電子工程協會) 754,任意一個二進制浮點數可以表示成下面的形式:
(-1)^S * M * 2^E
S是符號位(為0時浮點數為正,為1時浮點數為負),M為有效數字(大于1小于2),2^E表示指數位(決定了這個數的大小)。
讓我們來舉例說明:
浮點數8.5f轉換成二進制為1000.1,S為0,M為1.0001,E為 3
=(-1)^0 * 1.0001 * 2^3
所以我們只要在內存中儲存S、M和E三個數字就可以儲存浮點型數據了,實際上也是那么操作的。
接下來我們用圖來解釋內部的儲存邏輯:
IEEE 754規定,在計算機內部保存M時,默認這個數的第一位總是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01的時候,只保存01,等到讀取的時候,再把第一位的1加上去。這樣做的目的,是節省1位有效數字。以32位浮點數為例,留給M只有23位,將第一位的1舍去以后,等于可以保存24位有效數字。
我們要知道,E是一個無符號整型數字,這意味著,如果E為8位,它的取值范圍為0~255;如果E為11位,它的取值范圍為0~2047。
但是,我們知道,科學計數法中的E是可以出現負數的,所以IEEE 754規定,存入內存時E的真實值必須再加上一個中間數,對于8位的E,這個中間數是127;對于11位的E,這個中間數是1023。比如,2^10的E是10,所以保存成32位浮點數時,必須保存成10+127=137,即10001001。
然后,指數E從內存中取出還可以再分成三種情況:
E不全為0或不全為1
這時,浮點數就采用下面的規則表示,即指數E的計算值減去127(或1023),得到真實值,再將
有效數字M前加上第一位的1。
以8.5f為例
#include<stdio.h>
// 8.5f
// S為0,M為1.0001,E為 3 + 127
// 0 10000010 00010000000000000000000
// S E M
// 0100 0001 0000 1000 0000 0000 0000 0000
// 轉換為16進制為41 08 00 00
//
int main()
{
float a = 8.5f;
return 0;
}
因為是小端儲存,內存中存儲的內容與推斷一致。
E全為0
這時,浮點數的指數E等于1-127(或者1-1023)即為真實值,有效數字M不再加上第一位的1,而是還原為0.xxxxxx的小數。這樣做是為了表示±0,以及接近于0的很小的數字。
E全為1
這時,如果有效數字M全為0,表示±無窮大(正負取決于符號位s)。
int main()
{
int n = 1;//E全為0
float* pFloat = (float*)&n;
printf("*pFloat的值為:%.100f\n", *pFloat);
n = -1;//E全為1
printf("*pFloat的值為:%.100f\n", *pFloat);
return 0;
}
原文鏈接:https://blog.csdn.net/JDSZGLLL/article/details/124978089
相關推薦
- 2022-04-10 C#實現泛型動態循環數組隊列的方法_C#教程
- 2022-12-10 Redis數據庫安全詳解_Redis
- 2022-06-12 C#泛型接口的協變和逆變_C#教程
- 2023-02-08 Pytorch中torch.repeat_interleave()函數使用及說明_python
- 2022-01-30 tortoisegit pull時報錯
- 2022-02-11 Command line is too long. Shorten command line for
- 2023-05-29 Python?input輸入超時選擇默認值自動跳過問題_python
- 2022-08-10 pandas溫差查詢案例的實現_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支