Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Blad przy odejmowaniu liczby typu FLOAT
Forum PHP.pl > Forum > PHP
cagrET
Skrypt:
<?php echo 12.00 - 11.99; ?>

na linuxie wersja php 4.4.10 (sprawdzone na dwoch serwarach) wynik: 0.0099999999999998
na windowsie wersja php 4.3.9 wynik: 0.01

Ktos mial juz taki problem? I to jest duzy problem, bo blad ten pojawia sie w serwisie ecommerce, gdzie takie obliczenia sa istotne.

Na razie jedyne rozwiazanie jakie widze to wszedzie z obliczeniami gdzie wystepuje odejmowanie dodawac round:

<?php echo round(12.00 - 11.99, 2); ?>
s_w_ir
Może okaże sie że sie myle, ale uczyłeś się architektury komputerów? Liczby ułamkowe zapisywane w systemach dwójkowych są przeważnie przybliżeniem liczby którą chce sie zapisać. Jest to wynikiem ograniczonych mozliwości systemu dwójkowego np. liczba 0.3 ma w systemi dwójkowym rozwinięcie okresowe. Jeśli zapiszemy ją na 8 bitach tom po ponowym przekonwertowaniu jej na system dziesiętny otrzymamy 0,296875 czyli bląd na 1,05%( przykład zaczerpnięty z książki).
Jednak co jest śmieszne jeśli dodasz spowrotem to co odjołęś wynik będzie dobry smile.gif tzn = 12
  1. <?php
  2. $b=12.00 - 11.99;
  3. $b+=11.99;
  4. echo $b;
  5. ?>
cagrET
Juz mi paru linuxowcow dalo wyklad na temat cech i mantys. Ale oni nic nie rozumieja, ze po odjeciu 11.99 od 12.00 powinno byc 0.01. Bill Gates power O_o
s_w_ir
No powinno i nic nie poradzisz chyba że masz jakąs opcje żeby liczby kodować systemem dwójkowo-dziesiętnym- najbardziej dokładny do liczb zmienno przecinkowych ale też chyba bardziej pamięcio żerny- wymaga więcej bajtów na liczbe. Żeby sie za bardzo nie motać użyj ceil() lub round()
ghostrider
albo mozna pracowac na liczbach calkowitych i dopiero na samym koncu zamieniac na zmiennoprzecinkowe

  1. <?php
  2. $a = 12.00 * 100;
  3. $b = 11.99 * 100;
  4.  
  5. $c =( $a - $b)/100;
  6.  
  7. print $c; /* i git */
  8. ?>
mike
php zawsze było kiepskie w te klocki.
Skorzystaj z BCMath(arytmetyka liczb dużej precyzji)
  1. <?php
  2.  
  3. echo bcsub( 12.00, 11.99, 2 );
  4.  
  5. ?>
sobstel
ja tylko dodam ze problem ten oczywiscie dotyczy zarowno linuxa jak i windowsa. (btw - nie na temat - mysqla tez dlatego tam gdzie mozna i tam gdzie bedziemy stosowac porownania itp. to lepiej stosowac DECIMAL niz FLOAT)
dr_bonzo
Cytat(ghostrider @ 2005-11-02 10:16:40)
albo mozna pracowac na liczbach calkowitych i dopiero na samym koncu zamieniac na zmiennoprzecinkowe

  1. <?php
  2. $a = 12.00 * 100;
  3. $b = 11.99 * 100;
  4.  
  5. $c =( $a - $b)/100;
  6.  
  7. print $c; /* i git */
  8. ?>

Jest tylko male ale, juz tutaj "tracisz precyzje":
$b = 11.99 * 100;

biggrin.gif

Ale gdy potrzebujesz jedynie 2 cyfr po przecinku -- wystarczy int, a na koniec podziel przez 100.
hwao
juz byl taki temat, o ile dobrze pamietam.

I to nie byla wina php z tego co pamietam to Seth pokazywal to samo w innych jezykach.

To wina komputera
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.