Delphi中的四捨五入函式

2021-05-02 17:20:32 字數 3524 閱讀 2740

一、四捨五入法

四捨五入是一種應用非常廣泛的近似計算方法,其有算術捨入法和銀行家捨入法兩種。

所謂算術捨入法,就是我們通常意義上的四捨五入法。其規則是:當捨去位的數值大於等於

5時,在捨去該位的同時向前位進一;當捨去位的數值小於

5時,則直接捨去該位。

所謂銀行家捨入法,其實質是一種四捨六入五留雙(又稱四捨六入五奇偶)法。其規則是:當捨去位的數值小於

5時,直接捨去該位;當捨去位的數值大於等於

6時,在捨去該位的同時向前位進一;當捨去位的數值等於

5時,如果前位數值為奇,則在捨去該位的同時向前位進一,如果前位數值為偶,則直接捨去該位。

綜上所述,兩種捨入法所得結果不盡一致,因此在使用時必須根據實際需要加以區別。否則會出現一些莫明其妙的偏差。

二、delphi

中的四捨五入函式

眾所周知,

delphi

中有乙個四捨五入取整函式

round

。但它是按銀行家捨入法的規則實施捨入操作的,

delphi

中沒有按算術捨入法規則實施捨入操作的四捨五入取整函式。

在delphi

中使用四捨五入函式一直是使用

round,

可是有時候發現,使用它得到的答案與我們預期的會不太一樣。

舉例:i := round(11.5)    

結果: i=12

i := round(10.5)    

結果: i=10

是的,按照我們的預期,第二個函式應該返回

11才對,可是,為什麼會這樣呢?

對於***.5

的情況,整數部分是奇數,那麼會

round up

,偶數會

round down

。難道是

delphi

的bug?

no!!

讓我們看看

《精要>>

上的一句話:"

在最近版本的

delphi pascal

編譯器中,

round

函式是以

cpu

的fpu (

浮點部件

) 處理器為基礎的。這種處理器採用了所謂的

"銀行家捨入法

",即對中間值(如

5.5、

6.5)

實施round

函式時,處理器根據小數點前數字的奇、偶性來確定捨入與否,如

5.5 round

結果為6

,而6.5 round

結果也為

6, 因為

6 是偶數"。

round

函式其實使用的銀行家演算法進行運算的,統計學上一般也是使用這種演算法的,這比我們傳統的四捨五入方法要科學,可是,如果我們要使用傳統的四捨五入的方法,該如何解決呢?

有人是這樣解決的,給

10.5

加上乙個很微小的數值,再呼叫

round

函式,這樣在不影響精度的同時,就得到了正確的結果,貌似不錯,可這始終是治標不治本的方法,有沒有更正統的解決方法呢?

在網上又搜到了乙個函式:

function doround(value: extended): int64;

procedure set8087cw(newcw: word);

asmmov default8087cw,ax

fnclex

fldcw default8087cw

end;

const

roundupcw = $1b32;

varoldcw : word;

begin

oldcw := default8087cw;

try

set8087cw(roundupcw);

result := round(value);

finally

set8087cw(oldcw);

end;

end;

先解釋一下

8087cw,

全稱是8087 control word

。它是cpu

中浮點單元

(fpu)

控制器控制字的值,設定

8087cw

,會改變

fpu的精度,捨入模式,以及運算出錯時是否產生異常。

上面程式的思路很簡單,就是先儲存

8087cw,

然後設定它為

round up,

這樣偶數時就不會

round down

了,最後再還原

8087cw

。其實上面的函式還可以簡化,因為

system

單元裡已經提供了

set8087cw

的實現,所以程式簡化為

function doround(value: extended): int64;

const

roundupcw = $1b32;

varoldcw : word;

begin

oldcw := default8087cw;

tryset8087cw(roundupcw);

result := round(value);

finally

set8087cw(oldcw);

end;

end;

到這裡為止,這篇文章可以告一段落了,可是,經過摸索,我發現另一種相似而有趣的解決方案。

其實borland

早就想到我們會遇到這樣的問題,想到我們需要定製

fpu的捨入模式,所以它提供了現成的函式供我們使用。在

math

單元裡,有乙個

setroundmode

函式。下面是我封裝的乙個四捨五入函式:

function roundex(value: extended; roundmode: tfpuroundingmode = rmup): int64;

varrm: tfpuroundingmode;

begin

rm := getroundmode;

trysetroundmode(roundmode);

result := round(value);

finally

setroundmode(rm);

end;

end;舉例:

i := roundex(11.5)    

結果: i=12

i := roundex(10.5)    

結果: i=11

嗯,這樣對了吧,如果我設定成其它

roundmode

會怎樣呢?舉例:

i := roundex(11.5, rmtruncate)    

結果: i=11

i := roundex(10.5, rmtruncate)    

結果: i=10

roundex

函式華麗的變身為

trunc

函式了,是不是很有趣啊,哈哈

!

Delphi的四捨五入函式

小中 大一 四捨五入法 四捨五入是一種應用非常廣泛的近似計算方法,其有算術捨入法和銀行家捨入法兩種。所謂算術捨入法,就是我們通常意義上的四捨五入法。其規則是 當捨去位的數值大於等於5時,在捨去該位的同時向前位進一 當捨去位的數值小於5時,則直接捨去該位。所 謂銀行家捨入法,其實質是一種四捨六入五留雙...

Delphi的四捨五入函式

一 四捨五入法 四捨五入是一種應用非常廣泛的近似計算方法,其有算術捨入法和銀行家捨入法兩種。所謂算術捨入法,就是我們通常意義上的四捨五入法。其規則是 當捨去位的數值大於等於5時,在捨去該位的同時向前位進一 當捨去位的數值小於5時,則直接捨去該位。所謂銀行家捨入法,其實質是一種四捨六入五留雙 又稱四捨...

qt的四捨五入 Qt(C )四捨五入

qt現在是四捨六入五成雙,要想四捨五入得自己想辦法,實現如下 include include double c1 3.435 double c2 3.445 double c3 3.4351 double c4 3.4451 double c5 3.445 qdebug qdebug qdebug ...