網(wǎng)站首頁 編程語言 正文
我們都知道單精度浮點數(shù)(Single,float,Real)由32位0或1組成,它具體是如何來的。
浮點數(shù)的32位N=1符號位(Sign)+8指數(shù)位(Exponent)+23尾數(shù)部分(Mantissa)
- 符號位(Sign) : 0代表正,1代表為負(fù)【占1位】
- 指數(shù)位(Exponent)::用于存儲科學(xué)計數(shù)法中的指數(shù)數(shù)據(jù),并且采用移位存儲【占8位】
- 尾數(shù)部分(Mantissa):尾數(shù)部分【占23位】
- 單精度float:N共32位,其中S占1位,E占8位,M占23位。因此小數(shù)點后最多精確到23/4=6位 。
C#代碼示例如下
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConverterAndPrecisionDemo
{
? ? class Program
? ? {
? ? ? ? static void Main(string[] args)
? ? ? ? {
? ? ? ? ? ? //參考博客:https://blog.csdn.net/zhengyanan815/article/details/78550073
? ? ? ? ? ? //小數(shù)點后面:4個位占用一個數(shù)字【十進(jìn)制9就是1001】
? ? ? ? ? ? //符號位(Sign) : 0代表正,1代表為負(fù)【占1位】
? ? ? ? ? ? //指數(shù)位(Exponent):用于存儲科學(xué)計數(shù)法中的指數(shù)數(shù)據(jù),并且采用移位存儲【占8位】
? ? ? ? ? ? //尾數(shù)部分(Mantissa):尾數(shù)部分【占23位】
? ? ? ? ? ? //單精度float:N共32位,其中S占1位,E占8位,M占23位。因此小數(shù)點后最多精確到23/4=6位?
? ? ? ? ? ? //雙精度double:N共32位,其中S占1位,E占11位,M占52位。因此小數(shù)點后最多精確到52/4=13位?
? ? ? ? ? ? //十進(jìn)制小數(shù)的二進(jìn)制表示:【法則--整數(shù)部分:除基取余,逆序拼接。小數(shù)部分:乘基取整,順序拼接】
? ? ? ? ? ? //整數(shù)部分:除以2,取出余數(shù),商繼續(xù)除以2,直到得到0為止,將取出的余數(shù)逆序。可以使用棧Stack
? ? ? ? ? ? //小數(shù)部分:乘以2,然后取出整數(shù)部分,將剩下的小數(shù)部分繼續(xù)乘以2,然后再取整數(shù)部分,一直取到小數(shù)部分為零為止。如果永遠(yuǎn)不為零,則按要求保留足夠位數(shù)的小數(shù),最后一位做0舍1入。將取出的整數(shù)順序排列。可以使用隊列Queue
? ? ? ? ? ? float f = 123456.8125F;
? ? ? ? ? ? byte[] buffer = BitConverter.GetBytes(f);
? ? ? ? ? ? Console.WriteLine("打印浮點數(shù)對應(yīng)的4個字節(jié):");
? ? ? ? ? ? Console.WriteLine(string.Join(",", buffer));
? ? ? ? ? ? Console.WriteLine($"【使用函數(shù)】{123456}對應(yīng)的二進(jìn)制:{ Convert.ToString(123456, 2)}");
? ? ? ? ? ? int num = 123456;
? ? ? ? ? ? Stack<int> stack = new Stack<int>();
? ? ? ? ? ? while (num != 0)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? int cur = num % 2;
? ? ? ? ? ? ? ? stack.Push(cur);
? ? ? ? ? ? ? ? num = num / 2;
? ? ? ? ? ? }
? ? ? ? ? ? Console.WriteLine($"【使用堆棧】{123456}對應(yīng)的二進(jìn)制:{ string.Join("", stack)}");
? ? ? ? ? ? int scale = 10;
? ? ? ? ? ? int index = 0;
? ? ? ? ? ? double d = 0.8125;
? ? ? ? ? ? Queue<int> queue = new Queue<int>();
? ? ? ? ? ? while (index < scale)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? int cur = (int)(d * 2);
? ? ? ? ? ? ? ? queue.Enqueue(cur);
? ? ? ? ? ? ? ? d = d * 2 - cur;
? ? ? ? ? ? ? ? if (d == 0)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? index++;
? ? ? ? ? ? }
? ? ? ? ? ? Console.WriteLine($"{0.8125}對應(yīng)的二進(jìn)制:{ string.Join("", queue)}");
? ? ? ? ? ? string binaryDisplay = string.Join("", stack) + "." + string.Join("", queue);
? ? ? ? ? ? Console.WriteLine($"{123456.8125}對應(yīng)的二進(jìn)制為{binaryDisplay}");
? ? ? ? ? ? int dotIndex = binaryDisplay.IndexOf('.');
? ? ? ? ? ? //移除小數(shù)點后將小數(shù)點插入索引1的位置【即:小數(shù)點移動到索引1的位置】
? ? ? ? ? ? string scienceDisplay = binaryDisplay.Remove(dotIndex, 1).Insert(1, ".");
? ? ? ? ? ? Console.WriteLine($"小數(shù){123456.8125}對應(yīng)的二進(jìn)制科學(xué)計數(shù)為{scienceDisplay}×(2的{dotIndex - 1}次方)");
? ? ? ? ? ? string sign = (f > 0 ? "0" : "1");//符號位占用1位
? ? ? ? ? ? Console.WriteLine($"符號位S:正數(shù)為0,負(fù)數(shù)為1。符號位是:{sign}");
? ? ? ? ? ? string exponent = Convert.ToString(127 + (dotIndex - 1), 2).PadLeft(8, '0');//指數(shù)位占用8位
? ? ? ? ? ? Console.WriteLine($"指數(shù)位E:123456最高位為2的{dotIndex - 1}次方,指數(shù)為{dotIndex - 1},因此指數(shù)位E的十進(jìn)制值為【127+{dotIndex - 1}={127 + dotIndex - 1}】");
? ? ? ? ? ? //尾數(shù)部分:去除scienceDisplay開始的"1.",也就是字符串從索引2開始。并湊夠23位
? ? ? ? ? ? string mantissa = scienceDisplay.Substring(2).PadRight(23, '0');//尾數(shù)位占用23位
? ? ? ? ? ? Console.WriteLine($"尾數(shù)位M:尾數(shù)部分M需要湊夠23位。為【{mantissa}】");
? ? ? ? ? ? string joinBits = sign + exponent + mantissa;//符號位占用1位+指數(shù)位占用8位+尾數(shù)位占用23位=32位
? ? ? ? ? ? byte[] bufferJoin = new byte[4];
? ? ? ? ? ? for (int i = 0; i < 4; i++)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? bufferJoin[i] = Convert.ToByte(joinBits.Substring(8 * i, 8), 2);
? ? ? ? ? ? }
? ? ? ? ? ? Console.WriteLine("重新拼接形成的32位浮點數(shù),對應(yīng)的4個字節(jié)為:");
? ? ? ? ? ? Console.WriteLine(string.Join(",", bufferJoin));
? ? ? ? ? ? byte[] reverseBuffer = bufferJoin.Reverse().ToArray();
? ? ? ? ? ? Console.WriteLine("反轉(zhuǎn)數(shù)組bufferJoin的順序:重新打印我們會發(fā)現(xiàn)與浮點數(shù)原始的字節(jié)完全一致。注意:C#是低字節(jié)在前");
? ? ? ? ? ? Console.WriteLine(string.Join(",", reverseBuffer));
? ? ? ? ? ? Console.ReadLine();
? ? ? ? }
? ? }
}
程序運(yùn)行結(jié)果
關(guān)于32位浮點數(shù)的一些理解
1、定點的缺點
對于一個系統(tǒng)可能出現(xiàn)一些特別大的數(shù)和特別小的數(shù),如果用定點表示就會很僵硬,位數(shù)一定就不能同時表達(dá)特別大的數(shù)和特別小的數(shù)。
2、對于定點123.625
用科學(xué)計數(shù)法的方式可以寫成1.23625*10^2,也可以寫成12.625*10^1或1.111011101*2^6。。。。。為了規(guī)范,IEEE就規(guī)定了32位浮點的格式如下
3、翻譯一下
(1)最高位是符號位,“0”代表正,“1”代表負(fù)。
(2)接下來的8位是指數(shù)位,8位可表示整數(shù)的范圍是0-255,考慮指數(shù)可以是負(fù)的,IEEE規(guī)定在上面的范圍減去127,并將-127(全0)和128(全1)用做特殊值處理,所以指數(shù)的位的范圍是(-127,128)。
(3)最低的23位是小數(shù)位(尾數(shù)位),正常是可以表示23位的范圍,但是IEEE規(guī)定小數(shù)點左側(cè)必須為1,右側(cè)位數(shù)不夠補(bǔ)0。這樣可以就可以省略1,可以用23位來表示24位。
eg. 1.111011101*2^6中,小數(shù)位是111011101+補(bǔ)14個0
4、定點轉(zhuǎn)浮點實例:123.625用32位浮點表示
科學(xué)計數(shù)法=1.111011101*26(整數(shù)部分:123=01111011b,小數(shù)部分:0.625=0.101b,整數(shù)部分除2取余,倒序排列,高位補(bǔ)零;小數(shù)部分乘2取整,順序排列)
符號位:0
指數(shù)位:6+127=10000101
小數(shù)位:11101110100000000000000
即:01000010111101110100000000000000=0x42F74000
5、驗證
6、浮點轉(zhuǎn)定點實例
42F74000=01000010111101110100000000000000,拆分為符號位、指數(shù)位、小數(shù)位。
(1)符號位:0
(2)指數(shù)位:10000101=133,實際指數(shù)=133-127=6
(3)小數(shù)位:11101110100000000000000去掉后面的0、前面補(bǔ)1為1. 111011101
即科學(xué)計數(shù)法表示為1. 111011101*26=(2^0+2^-1+2^-2+2^-3+2^-5+2^-6+2^-7+2^-9)*2^6=123.625。
原文鏈接:https://blog.csdn.net/ylq1045/article/details/108025459
相關(guān)推薦
- 2022-10-12 Python?Pandas的concat合并_python
- 2022-11-15 C++構(gòu)造析構(gòu)賦值運(yùn)算函數(shù)應(yīng)用詳解_C 語言
- 2023-02-15 go性能分析工具pprof的用途及使用詳解_Golang
- 2022-08-20 python深入講解魔術(shù)方法_python
- 2022-05-22 ansible管理工具的環(huán)境及部署安裝_服務(wù)器其它
- 2023-10-15 理解C/C++中的鏈接
- 2022-08-15 對稱式加密和非對稱加密的對比
- 2022-12-05 Django中使用AJAX的詳細(xì)過程_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支