久久ER99热精品一区二区-久久精品99国产精品日本-久久精品免费一区二区三区-久久综合九色综合欧美狠狠

新聞中心

EEPW首頁 > 測試測量 > 設計應用 > 學習LabVIEW(十)——關于Matlab的eps函數(十三)

學習LabVIEW(十)——關于Matlab的eps函數(十三)

作者: 時間:2017-01-09 來源:網絡 收藏
關于Matlab的eps函數的實現原理,我以前寫過十幾篇短文了。其中最接近官方的版本可以參考《關于Matlab的eps函數(十)——MATLAB Coder生成的C代碼》。那時使用了MATLAB的Coder直接生成了一份eps的C語言版本,應該就是官方的實現方式了。
為什么這么關注eps函數?因為對于數值分析而言,eps是非常重要的,它展示了基于IEEE754浮點數的一個基本屬性:相對浮點精度。然而,盡管eps如此重要,能夠說清楚eps運算方法的人寥寥無幾。現代社會,人人都要會編程,然而如果只是接受了普通的編程入門學習,沒有像計算機專業科班出身的那群人那樣花了好多好多的學時學習數值分析的話,就會傾向于將計算機中的浮點數與數學中的實數這個概念等價起來。可事實卻是:浮點數和數學概念中的實數有著巨大的差異。比如,概念中的實數,是可以連續取值的。而基于754標準的浮點數,則和整數類似,取值是離散的!而eps正是衡量一個浮點數取值到下一個浮點數取值之間的距離的工具。與整數不同的是,浮點數之間的間隔不是一成不變,而是隨著浮點數數值的變化而變化的;所以eps不是一個常數而是一個函數。
  • 在《關于Matlab的eps函數》中,我們討論了eps的本質,并使用Matlab的typecast函數(用來實現reinterpret cast)實現了eps的計算;
  • 在《關于Matlab的eps函數(續)》,《關于Matlab的eps函數(又續)》,《關于Matlab的eps函數(六)》和《關于Matlab的eps函數(七)——“又續”的續》中,我們利用位段結構體實現了eps計算,這種版本的可讀性比最初用typecast實現的版本要好多了;
  • 在《關于Matlab的eps函數(再續)》中,我們根據mathworks上的一個帖子,討論了利用純粹的數學運算而不是位運算實現eps的方法;
  • 在《關于Matlab的eps函數(五)》和《Article 4 in 1: 關于Matlab的eps函數(八) &讀Matlab7.7的rank函數 &讀Matlab7.7的orth》中,討論了eps函數的幾個實際應用;
  • 在《關于Matlab的eps函數(九)——Java也有"eps"函數》中,我們展示了Java中,與eps功能類似的方法ulp的用法,并討論了ulp和eps的不同;
  • 在《關于Matlab的eps函數(十)——MATLAB Coder生成的C代碼》中,我們通過MATLAB Coder窺見了官方的eps實現方法;
  • 在《GPU Powered Matlab(三)——關于Matlab的eps函數(十一)》和《GPU Powered Matlab(三點一)——關于Matlab的eps函數(十二)》中,我們試著將eps搬到CUDA GPU上執行。
今天要做的事情,是在LabVIEW中用純粹的G語言實現eps運算。其實我現在并不需要在LabVIEW中使用eps,只是想通過實現eps來了解LabVIEW到底有多強的位運算能力。
首先,LabVIEW在“編程->數值”中提供了名為“計算機?”的節點,這個節點是一個常數節點(而非函數),其數值等于MATLAB中的eps(1):


上圖中數值顯示控件“數值3”輸出的數值為0,說明LabVIEW節點“計算機?”和Matlab的eps(1)相等。實際上,由于MATLAB的函數支持可變個數的參數,且函數調用的時候可以省去括號,因此eps(1)也可以寫成eps這種形式,這就是導致很多人認為Matlab中的eps是一個常數而非函數的原因。如果勤快的話,在Matlab的Command Window中敲上一行“doc eps”就能看到關于eps的更多信息。
既然“計算機?”節點不是函數,我們就需要自己添加額外的程序來實現eps的功能了。實際上,C++中也提供了eps(1)的數值,而我們在《關于Matlab的eps函數(六)》中的實現方式,就是用位運算的方式獲取給定的浮點數R的指數部分E,然后使用表達式
eps(1) * 2 ^ E
得到了eps(R)的值。這里我們也可以使用這種手法。
為了提取浮點數的指數部分,我們首先測試一下LabVIEW的位運算能力。想要對浮點數進行位操作,就需要語言提供一種reinterpret cast的機制。在Matlab中是typecast,而LabVIEW也提供了typecast,根據文檔,LabVIEW的typecast節點可以實現:
*(type *) &R
的變換,正是我們所需要的。
浮點數本質上和整數沒有區別,就是內存中的幾個字節的集合,里面的位的取值包含了信息。和整數唯一的不同就是解讀這些位的方式。然而沒有學過低階語言的編程者,受到了高階語言編譯器/解釋器的照顧,浮點數的存儲和計算這些細節完全被語言的機制所掩蓋。這是一件好事,因為大家編程的時候就不用關心太多的細節。這也是一件壞事,讓大家不用去了解浮點數的底層機制。時間長了,大家就形成了錯誤的印象:既然語言不讓我對浮點數做位操作,那浮點數大概就是不能做位操作的吧。我以前在大學的時候,隔壁有一個項目組,因為不知道如何在C語言中將浮點數拆成字節數組以放到串口緩沖區中,差點連硬件電路都改了。
LabVIEW的typecast的用法幾乎和Matlab的typecast函數一樣。我們先復習一下Matlab的typecast函數。
首先將輸出格式調成16進制:
>> format hex
取一個雙精度浮點數15,轉換成字節數組:
>> bytes = typecast(15, uint8)

bytes =

0000000000002e40

我們知道,浮點數是由符號,指數,尾數三個部分組成的。這里試著將字節數組最后一個字節的最高位改成1,對應的浮點數就是符號位變成1,會變成負數:
>> bytes(end) = hex2dec(c0);
>> format; dbl = typecast(bytes, double)

dbl =

-15

再試試對浮點數的指數部分進行操作。雙精度浮點數有8個字節,64位。其中符號位1位,指數位11位,尾數位52位,如果想把指數加上1(等效于浮點數乘以2),只需要執行下面的操作:
>> typecast(typecast(15, uint64) bitshift(uint64(1), 52), double)

ans =

30

首先將雙精度浮點數15 reinterpret成unsigned int64,然后加上1左移52位,再reinterpret成double。就是這么簡單。

上一頁 1 2 下一頁

關鍵詞: LabVIEWMatlabeps函

評論


技術專區

關閉