999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

探討Visual C++2010環境下浮點型數據的存儲形式

2020-09-27 23:02:21王兆華
電腦知識與技術 2020年23期

王兆華

摘要:針對高校本科生課程《C語言程序設計》中有關浮點數數據類型的認識和使用中出現的問題,學生存在對浮點數的認知不夠清晰,對Visual C++2010環境下有關浮點數的相關計算結果存在各種困惑。根據多年的教學經驗,查閱相關書籍和IEEE754標準,論文分析Visual C++2010環境下浮點型數據的存儲形式,闡述了有關浮點數相關幾個重要知識點的理解。文中引入計算思維的指導思想,采用從現象到本質,從理論到實踐來逐步解決問題。實踐證明,該方法取得的了較好的學習效果,夯實了學生對基礎知識的掌握和正確應用。

關鍵詞:浮點數;IEEE754;存儲形式;Visual C++2010環境;計算思維

中圖分類號:TP311? ? ? ? 文獻標識碼:A

文章編號:1009-3044(2020)23-0041-04

Abstract: In view of the problems in the understanding and use of floating point data types in the undergraduate course C Language Programming, students are not clear enough about Floating point number, and they are confused about the calculation results of Floating point data in the Visual C++2010 environment. According to years of teaching experience, consult relevant books and IEEE754 standard, the paper analyzes the storage form of floating point number in Visual C++2010 environment, and expounds the understanding of several important knowledge points related to floating point Numbers. This paper introduces the guiding ideology of computational thinking and solves the problem step by step from phenomenon to essence and from theory to practice. The practice has proved that the method has achieved a good learning effect .The students' mastery and correct application of basic knowledge are consolidated.

Key words:floating point number; IEEE754; storage form; visual C++2010 environment; computational thinking;

1 引言

C語言是最受歡迎、最重要的和最流行的編程語言之一。《C語言程序設計》課程是大部分大學本科理工類學生的一門必修課。C語言有豐富的數據類型,在介紹數據類型一章會介紹基本類型中的整型、字符型、浮點型。在這三種基本類型中浮點型是課程教學的重點和難點,根據多年的教學經驗積累,筆者深入研究了Visual C++2010環境下浮點型數據的存儲形式,梳理教學重點和難點,引入計算思維的思想,使得學生更容易理解浮點數的存儲形式。

周以真教授認為:計算思維(Computational Thinking)是運用計算機科學的基礎概念進行問題求解、系統設計以及人類行為理解等涵蓋計算機科學之廣度的一系列思維活動[1]。它包括了涵蓋計算機科學之廣度的一系列思維活動。當我們必須求解一個特定的問題時,首先會問:解決這個問題有多么困難?怎樣才是最佳的解決方法?計算機科學根據堅實的理論基礎來準確地回答這些問題。表述問題的難度就是工具的基本能力,必須考慮的因素包括機器的指令系統、資源約束和操作環境。

本文的思路是首先通過實踐發現浮點數計算中存在的問題,為什么結果不準確?為什么會存在一些錯誤判斷。要想弄清楚這些問題,需要清楚理論知識和計算機的操作環境,以及計算機計算能力的限制。

2 拋出問題

在使用浮點數的時候,我們發現一些問題:

(1)一個浮點數不能準確的輸出,為什么?程序代碼如下:

#include

int main()

{

float fa=56.982f;

printf("fa=%f\n",fa);

return 0;

}

這個程序的執行結果是:fa=56.981998,而不是fa=56.982。

(2)一個浮點數與一個極小的浮點數求和,結果不正確,為什么?程序代碼如下:

#include

int main()

{

float fa=2.5f;

fa=fa+0.0000001f;

printf("fa=%f\n",fa);

return 0;

}

這個程序的執行結果是:fa=2.500000,而不是fa=2.5000001。

(3)數學上兩個不相等的浮點數程序卻認為是相等的,為什么?程序代碼如下:

#include

int main()

{

float fa=1.00000001f,fb=1.00000002f;

if(fa==fb)

printf("兩個數相等!\n");

return 0;

}

這個程序的執行結果是:“兩個數相等!”,顯然是錯誤的。

筆者所給的三個程序的運行環境是Win7+Visual C++2010,因此帶著這幾個疑問,有必要深入研究一下在這樣的編譯和運行環境下浮點數的存儲形式。

3 IEEE754標準

浮點數是指小數點位置根據需要可以浮動的數據,浮點數的一般表示形式為:N=RE×D,其中N為浮點數,R稱為基數,E稱為階碼,D稱為尾數。如圖1所示。

R為一常數,與尾數的基數相同,一般為2、8、或16,在一臺計算機中,所有數據的R都是相同的,不需要在每個數據中表示出來。任意一個二進制浮點數N可以表示為:N=2E×D。

在浮點數表示中,即使數據字長相同時,不同的計算機可能選用不同的格式、不同的階碼與尾數位數及其編碼,從而導致不同計算機之前浮點機器數差異很大,不利于軟件移植,為此,美國電氣電子工程師協會于1985年提出了浮點機器數IEEE754標準,并得到廣泛應用[2]。在軟件中IEEE 754以浮點庫的形式實現,在硬件(如許多CPU和FPU)中的指令中實現。 第一個實現IEEE 754-1985草案的集成電路是Intel 8087。

當今流行的計算機幾乎都采用IEEE754浮點數標準,在這個標準中,每個浮點數均由數符S、階碼E、尾數M三部分組成。用三元組{S,E,M}表示一個數N,如圖2所示。

IEEE754標準規定了四種浮點數的表示方式:單精確度(32位)、雙精確度(64位)、延伸單精確度(43比特以上,很少使用)與延伸雙精確度(79比特以上,通常以80比特實做)。C語言中float和double浮點型分別對應的是單精度和雙精度浮點數,下面以單精度浮點數為例介紹浮點數的存儲形式,如圖3所示:單精度浮點數(32位):N共32位,其中S占1位,E占8位,M占23位。

單精度浮點數根據階碼和尾數的取值情況分為:0,非規格化數,規格化數,無窮和NaN(Not a Number,非數)。如表1所示。

浮點數的尾數采用補碼形式存儲,階碼采用移碼形式存儲。下面需要清楚什么是補碼和移碼。

4 原碼、反碼、補碼、移碼的概念

要想了解浮點數在計算機中的存儲學生務必清楚原碼、反碼、補碼、移碼相關概念。原碼、補碼,反碼是把符號和數值一起編碼的表示方法,是機器數的表示形式。

(1)原碼:是用“符號碼+二進制絕對值”表示的機器碼。符號碼用0表示正,用1表示負。

(2)反碼:引入反碼是為了求負數的補碼。正數的反碼與原碼相同,負數的反碼除符號位不變外,其余各位取反。

(3)補碼:補碼的引入是為了在計算機中把減法運算轉換為加法運算。使減法運算變得簡單,在計算機中容易實現。正數的補碼與原碼相同,負數的補碼在反碼的末尾加1。

(4)移碼:又稱為增碼或偏碼,在計算機中主要用于表示浮點數的階碼,而階碼是整數,因此階碼僅需要定點證書編碼法。移碼實質是在真值X基礎上加一個固定正整數(稱為偏置值),把真值映射到一個正數域,相當于在數軸上將真值X向正方向平移一段距離,這也是該編碼命名為“移碼”的來由。對于二進制純整數,移碼與真值得映射式為:[X]移=偏置值+X。偏置值選取的原則是使真值X中絕對值最大的負數對應的編碼量值為0,因此偏置值一般取2n。當偏置值取2n時,移碼與真值得映射式為:[X]移=2n+X (-2n <=X<=(2n-1))。

純整數偏置值2n移碼與補碼之間的關系為:同一純整數真值的偏置值2n移碼與補碼,它們的有效數值位相同,符號位互反。

清楚補碼和移碼編碼之后,對于多個字節的浮點數,在存儲器中應該怎么存儲呢?

5 計算機存儲的大端法和小端法

對于多字節的程序對象,必須建立兩個規則:這個對象的地址是什么,以及在存儲器中如何排列這些字節。在幾乎所有的機器上,多字節對象都被存儲為連續的字節序列,對象的地址為所使用在字節最小的地址。例如:假設在VC++2010中編譯的C程序中一個int的變量x的地址是a,那么x的4個字節將分別被存儲在存儲器地址為:a、a+1、a+2、a+3的四個存儲單元。

某些機器選擇在存儲器中按照從最低有效字節到最高有效字節的順序存儲對象,而另一些機器則按照從最高有效字節到最低有效字節的順序存儲。最低有效字節在前面的方式,稱為“小端法(little endian)”。最高有效字節在最前面的方式,稱為“大端法(big endian)”。大多數Intel兼容機都采用“小端法”的規則。大多數IBM和Sun Microsystems的機器都采用“大端法”的規則。IBM和Sun制造的個人計算機使用的是Intel兼容的處理器,因此使用的就是“小端法”。許多比較新的微處理器使用“雙端法(bi-endian)”,也就是可以把它們配置成作為大端或者小端的機器運行[3]。

示例:變量x類型為int,位于地址a,int型數據在VC++2010中占32字節,假如它的十六進制為0x01234567。采用“大端法”(圖4)和“小端法”(圖5)的存儲順序分別如圖4和圖5所示。

可以通過下面的程序確認機器所采用的存儲方式,代碼編譯運行平臺Win32 + VC++2010,機器為聯想ThinkPad T430,CPU型號是Intel酷睿i52520M。

#include

int main()

{

int x=0x01234567;

char *px=(char *)&x;

if(*px==0x01)? //判斷高字節0x01是否保存在低地址

printf("大端法\n");

else

printf("小端法\n");

return 0;

}

程序執行結果:“小端法”。

清楚了當前計算機采用的是“小端法”之后,需要通過程序來驗證浮點數的具體存儲形式。

6 Visual C++2010環境下單精度浮點數的具體存儲形式

下面以具體的數為例,在編譯環境下驗證浮點數的存儲形式。

(1)十進制0.5

第一步:把十進制0.5轉換為二進制結果為(0.5)10=(0.1)2。

第二步:把(0.1)2規格化為2e×D 即2-1× (1)2。

第三步:分別求解S,M,e,E。S=0, M=[000 0000 0000 0000 0000 0000]2,e=-1,E=e+127=126。

第四步:求解機器碼(實際存儲形式):[0.5]10= [0011 1111 0000 0000 0000 0000 0000 0000]2。

第五步:用十六進制表示機器數:3F000000。

(2)十進制1.25

第一步:把十進制1.25轉換為二進制結果為(1.25)10=(1.01)2。

第二步:把(1.01)2規格化為2e×D 即20× (1.01)2。

第三步:分別求解S,M,e,E。S=0, M=[010 0000 0000 0000 0000 0000]2,e=0,E=e+127=127。

第四步:求解機器碼(實際存儲形式):[1.25]10= [0011 1111 1010 0000 0000 0000 0000 0000]2。

第五步:用十六進制表示機器數:3FA00000。

(3)十進制-1.25

第一步:把十進制-1.25轉換為二進制結果為(-1.25)10=(-1.01)2。

第二步:把(-1.01)2規格化為2e×D 即20 ×(-1.01)2。

第三步:分別求解S,M,e,E。S=-1, M=[010 0000 0000 0000 0000 0000]2,e=0,E=e+127=127。

第四步:求解機器碼(實際存儲形式):[-1.25]10= [1011 1111 1010 0000 0000 0000 0000 0000]2。

第五步:用十六進制表示機器數:BFA00000。

(4)十進制124.25

第一步:把十進制124.25轉換為二進制結果為(124.25)10=( 1111100.01)2

第二步:把( 1111100.01)2規格化為2e×D 即26 ×( 1.11110001)2。

第三步:分別求解S,M,e,E。S=0, M=[111 1000 1000 0000 0000 0000]2,e=6,E=e+127=133。

第四步:求解機器碼(實際存儲形式):[124.25]10= [0100 0010 1111 1000 1000 0000 0000 0000]2。

第五步:用十六進制表示機器數:42F88000。

程序驗證(代碼編譯運行平臺Win32 + VC++2010):

#include

int main(void)

{

float fa=0.5,fb=1.25,fc=-1.25,fd=124.25;

unsigned int *pa=(unsigned int *)&fa;

unsigned int *pb=(unsigned int *)&fb;

unsigned int *pc=(unsigned int *)&fc;

unsigned int *pd=(unsigned int *)&fd;

printf("%.1f的內存存儲形式:%X\n",fa,*pa);

printf("%.2f的內存存儲形式:%X\n",fb,*pb);

printf("%.2f的內存存儲形式:%X\n",fc,*pc);

printf("%.2f的內存存儲形式:%X\n",fd,*pd) ;

return 0;

}

程序執行結果:

0.5的內存存儲形式:3F000000

1.25的內存存儲形式:3FA00000

-1.25的內存存儲形式:BFA00000

124.25的內存存儲形式:42F88000

可見程序的執行結果與上面的分析和計算結果是一致的。

在VC++2010的監視窗口(圖6)和內存窗口(圖7)觀察的結果如下圖所示。

清楚了Visual C++2010環境下單精度浮點數的具體存儲形式,需要進一步探討浮點數的取值范圍和精度問題。

7單精度浮點數的取值范圍和精度

主站蜘蛛池模板: 美女内射视频WWW网站午夜 | 日韩av手机在线| 亚洲欧美人成人让影院| 国产精品自在拍首页视频8| 日韩精品无码不卡无码| 伊人久久久大香线蕉综合直播| 日韩高清无码免费| www.精品视频| 亚洲黄色片免费看| 男人天堂伊人网| 福利一区三区| 成人看片欧美一区二区| 欧洲欧美人成免费全部视频 | 国产美女人喷水在线观看| 免费aa毛片| 成人一区在线| 欧美另类精品一区二区三区| 亚洲日本中文字幕天堂网| 国内精品一区二区在线观看 | 亚洲精品高清视频| 亚洲无码视频图片| 国产成人h在线观看网站站| 高清视频一区| 性视频一区| 嫩草影院在线观看精品视频| 91精品专区| 97国产在线播放| 久久91精品牛牛| 亚洲永久精品ww47国产| 久久成人免费| 激情无码视频在线看| 日本欧美中文字幕精品亚洲| 欧美性爱精品一区二区三区| 久久人午夜亚洲精品无码区| 精品视频在线观看你懂的一区| 亚洲美女一级毛片| 亚洲免费三区| 国产一级毛片yw| 亚洲欧美精品日韩欧美| 永久免费精品视频| 亚洲日韩精品欧美中文字幕| 在线免费看片a| 国产亚洲精久久久久久久91| 成人免费黄色小视频| 五月婷婷丁香综合| 亚洲精品无码成人片在线观看| 欧美日韩中文字幕二区三区| 亚洲日韩久久综合中文字幕| 国产91色在线| 亚洲va在线∨a天堂va欧美va| 成人亚洲天堂| 欧美国产综合色视频| 日韩欧美国产三级| 2020最新国产精品视频| 亚洲色图综合在线| 精品自拍视频在线观看| 日韩不卡高清视频| 亚洲视频二| 中文精品久久久久国产网址| 亚洲美女高潮久久久久久久| 亚洲精品无码抽插日韩| 伊人网址在线| 久久人搡人人玩人妻精品| jizz国产在线| 国产女人综合久久精品视| 福利视频一区| 婷婷伊人五月| 亚洲日韩精品无码专区97| 久久综合亚洲鲁鲁九月天| 国产美女免费| 99性视频| 亚洲久悠悠色悠在线播放| 欧美色图第一页| 麻豆国产在线观看一区二区 | 99热这里只有精品免费国产| 亚洲免费黄色网| 91成人免费观看在线观看| 欧美国产精品不卡在线观看| 色婷婷在线影院| 国产精品太粉嫩高中在线观看| 国产亚洲欧美另类一区二区| 中文字幕日韩欧美|