新聞中心

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

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

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


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

bytes =

0000000000002e40

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

dbl =

-15

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

ans =

30

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

上一頁(yè) 1 2 下一頁(yè)

關(guān)鍵詞: LabVIEWMatlabeps函

評(píng)論


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

關(guān)閉