2013-03-24 16 views
5

Przeczytałem Floating-Point guide o używaniu typu float w PHP. Odpowiedź jest przy użyciu rozszerzenia BC Math. Używanie łańcuchów może reprezentować zmienną float jako dokładny typ i zapobiegać problemom z float i integer.Najlepsza praktyka dla użycia zmiennoprzecinkowego PHP

Tymczasem nie znalazłem żadnych dobrych przykładów na Github i ta strona działa z rozszerzeniem matematycznym BC. Jaki jest czysty sposób na zmuszanie PHP do używania łańcuchów, jak je oceniać?

W szczególności, jaki jest najlepszy sposób używania rozszerzenia BC Math z typami danych MySQL DECIMAL?

Mój przykład testu z PHP 5.4.10, prawidłowa odpowiedź brzmi: 0,2999999999996

<?php 
bcscale(13); 

$a = '0.3'; 
$b = '0.0000000000004'; 

echo $a-$b; // 0.3 
echo '<br />'; 
echo bcsub($a, $b); // 0.2999999999996 
echo '<hr />'; 

$a = "0.3"; 
$b = "0.0000000000004"; 

echo $a-$b; // 0.3 
echo '<br />'; 
echo bcsub($a, $b); // 0.2999999999996 
echo '<hr />'; 

$a = 0.3; 
$b = 0.0000000000004; 

echo $a-$b; // 0.3 
echo '<br />'; 
echo bcsub($a, $b); // 0.3000000000000 
echo '<hr />'; 

$a = '0.3'; 
$b = '0.0000000000004' + 0; 

echo $a-$b; // 0.3 
echo '<br />'; 
echo bcsub($a, $b); // 0.3000000000000 
echo '<hr />'; 

$a = (string) 0.3; 
$b = (string) 0.0000000000004; 

echo $a-$b; // 0.3 
echo '<br />'; 
echo bcsub($a, $b); // 0.3000000000000 
echo '<hr />'; 

$a = strval(0.3); 
$b = strval(0.0000000000004); 

echo $a-$b; // 0.3 
echo '<br />'; 
echo bcsub($a, $b); // 0.3000000000000 
?> 
+1

um, co jest nie tak w pierwszym i drugim przypadku? Jeśli chcesz poznać "najlepszą" opcję, pojedyncze cudzysłowy "są lepsze niż podwójne" ", ponieważ PHP będzie wymagało poświęcenia dodatkowego czasu na wypełnianie nazw zmiennych i sekwencji unikowych, jeśli użyjesz podwójnych cudzysłowów. – Dave

+0

Dzięki za szybką odpowiedź Dave, używając tych pojedynczych cytatów wykonuje pracę. W jaki sposób będę mieć pewność, że mam odpowiednią wartość, zanim dane mogą zostać utracone. Na przykład przy pobieraniu wierszy z mysql – Mike

+0

@Dave, to po prostu nie jest prawdą w przypadku każdej najnowszej wersji php. Przeczytaj [ten artykuł] (http://nikic.github.com/2012/01/09/Disproving-the-Single-Quotes-Performance-Myth.html). – Maerlyn

Odpowiedz

4

Najlepszym sposobem jest, aby nie używać BC Math ale zacząć używać GMP. Wystarczy spojrzeć na on benchmark. GMP jest do 30 razy szybsza niż BC Math.

Używam DECIMAL (12, 0) I DECIMAL (27,0) i php start suck apr. o 10^19 i więcej. Demo:

//PHP Version 5.3.10, FreeBSD 8.2-RELEASE amd64 

$a = pow(10, 18); 
var_dump($a, $a > ($a - 1), ($a - 1) > $a, ($a - 1) == $a, ($a - 1) === $a); 
// int(1000000000000000000) 
// bool(true) 
// bool(false) 
// bool(false) 
// bool(false) 

$a = pow(10, 19); 
var_dump($a, $a > ($a - 1), ($a - 1) > $a, ($a - 1) == $a, ($a - 1) === $a); 

// double(1.0E+19) 
// bool(false) 
// bool(false) 
// bool(true) 
// bool(true) 

zrobiłem Decimal klasę, here is simple implementation. Później możesz zaimplementować ten sam interfejs, ale z natywnymi operacjami matematycznymi php lub z matematyką BC lub cokolwiek chcesz. Yupp, będzie narzut na wywoływanie funkcji i obiektów, ale piszemy kod, który inni deweloperzy mogą przeczytać, prawda?

P.S. Faceci z PHP Secure Communications mają własną implementację - Math_BigInteger, która pokrywa wszystkie potencjalne potrzeby, ale jest zbyt ciężka dla moich zadań.

Aktualizacja: od PHP 5.6 GMP realizowane internal operators overloading, więc GMP zasoby mogą być używane jako zwykłe numery (w większości).

Powiązane problemy