PHP Double 精度
在計算機(jī)編程中,精度一直是一個很重要的問題,其中雙精度浮點數(shù)(Double)精度更為嚴(yán)格,如果處理不當(dāng),容易導(dǎo)致數(shù)據(jù)誤差,從而產(chǎn)生很多的問題。今天,我就和大家分享一下 PHP Double 精度的相關(guān)知識。
Double 精度定義
Double 精度是指浮點數(shù)的數(shù)字類型,其精度在 15-16 位之間,具有比 Float 更高的精度。在 PHP 中,我們可以使用 浮點型(float) 或者 整型(integer) 和 雙精度浮點數(shù)(Double)來表示數(shù)字。其中,Double 最高達(dá)到了 1.79E+308 的精度,而 Float 則最高只能達(dá)到 3.4028235E+38。
Double 精度問題
由于 Double 精度較高,因此,在計算過程中,會遇到很多數(shù)字精度問題。PHP 中的 Double 精度問題主要集中于以下兩個方面:
1. 雙精度浮點數(shù)精度誤差問題(精度丟失)。
2. 一些 PHP 內(nèi)建函數(shù)在處理雙精度浮點數(shù)時會出現(xiàn)非常小的舍入誤差。
Double 精度誤差舉例介紹
Double 精度誤差是指在計算雙精度浮點數(shù)時,存在一定的精度誤差。這種精度誤差主要由于二進(jìn)制浮點數(shù)無法完全精確地表示出浮點數(shù)的大小而產(chǎn)生。下面,我們來看幾個計算例子:
如下代碼:
$x = 5068308842.7205; $y = 5068308842.7204; var_dump($x - $y); // float(0.000099999997764516)上面的代碼中,$x 和 $y 只是小數(shù)點后第 4 位不同,然而它們的的差異值(float(0.000099999997764516)) 卻達(dá)到了 15 位之多。這是因為在計算這個值的過程中,PHP 規(guī)定只要小數(shù)點后位數(shù)太多就會發(fā)生截斷。 再看下面這個例子:
$x = 0.7; $y = 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1; if ($x == $y) { echo "相等"; } else { echo "不相等"; } // 不相等在上面的代碼中,我們只是簡單地將 0.1 相加,明明是等于 0.7 的,但在 PHP 中,卻是不相等的。這是因為在計算 $y 的過程中,0.1 是不能被準(zhǔn)確地表示出來的,所以在相加的過程中出現(xiàn)了雙精度浮點數(shù)誤差。 常用方法解決 Double 精度誤差 下面,我們來介紹一些常見的解決方法。 1. 使用 bcmath 擴(kuò)展。 bcmath 擴(kuò)展,是 GMP bignum 擴(kuò)展的一種簡化實現(xiàn),它提供了一個高精度的任意精度數(shù)學(xué)庫。使用這個擴(kuò)展可以解決 PHP 中雙精度浮點數(shù)誤差的問題,同時還可以提供很多其它的高級數(shù)學(xué)操作。 如下代碼:
$x = 5068308842.7205; $y = 5068308842.7204; echo bcsub($x, $y, 16);// 0.0001上面的代碼,使用了 bcmath 擴(kuò)展,將雙精度浮點數(shù)變成了高精度數(shù),從而減少了精度誤差。 2. 將數(shù)字轉(zhuǎn)成整數(shù)再進(jìn)行計算。 把小數(shù)轉(zhuǎn)成整數(shù)可以保證不丟失小數(shù)精度。在計算完了之后,再把整數(shù)轉(zhuǎn)換成小數(shù)即可。 如下代碼:
$x = 1.23; $y = 4.56; echo ($x * 100) * ($y * 100) / 10000; //0.56088上面的代碼中,我們將小數(shù)轉(zhuǎn)成整數(shù),計算完之后再轉(zhuǎn)成小數(shù),從而避免了浮點數(shù)誤差。 總結(jié) 雙精度浮點數(shù)(Double)是計算機(jī)中用來表示小數(shù)的一種數(shù)字類型,具有比 Float 更高的精度。在 PHP 中,雙精度浮點數(shù)誤差主要表現(xiàn)在舍入誤差和精度誤差兩個方面。對于這些誤差,我們可以使用 bcmath 擴(kuò)展或者將數(shù)字轉(zhuǎn)成整數(shù)再進(jìn)行計算等方式來盡量減少誤差。