新聞中心

EEPW首頁 > 測試測量 > 設(shè)計應(yīng)用 > 學(xué)習(xí)LabVIEW(十)——關(guān)于Matlab的eps函數(shù)(十三)

學(xué)習(xí)LabVIEW(十)——關(guān)于Matlab的eps函數(shù)(十三)

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


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

bytes =

0000000000002e40

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

dbl =

-15

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

ans =

30

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

上一頁 1 2 下一頁

關(guān)鍵詞: LabVIEWMatlabeps函

評論


技術(shù)專區(qū)

關(guān)閉