Autor Zpráva
Anonymní
Profil *
Zdar! tak trochu zacinam s PHP a mam mensi problem.
Skusal som priklad podla jednej knihy, vyzeral asi takto:

<?php
$ABC = 0.3;
$XYZ = 0.4;
echo 0.7-$ABC-$XYZ;
?>


no takze teoreticky by to malo vyhodit vysledok 0 ale vypise to -5.5511151231258E-17
Autor pise ze realne cisla niesu uplne presne a ze nastane mala odchylka...
Ale ak skusim zmenit hodnoty nejak takto:

<?php
$ABC = 6.5;
$XYZ = 7.5;
echo 14.0-$ABC-$XYZ;
?>


tak je vysledok uplne normalny, 0.
Neviete mi teda poradit ze kedy ta odchylka nastane? Je to pre mna dost dolezite lebo ked budem pocitat a bude to hadzat vysledok -5.5511151231258E-17
hore-dole tak by to mohol byt dost velky problem.
dakujem
tiso
Profil
Anonymní: „Neviete mi teda poradit ze kedy ta odchylka nastane?
Nevieme.
_es
Profil
Anonymní
Ty to číslo zapíšeš v desiatkovej sústave, no ono sa prevedie do dvojkovej a to sa nedá pri všetkých číslách úplne presne.
Podobne ako v desiatkovej sústave nedokážeš úplne presne zapísať 1/3.
AM_
Profil
Pokud vím, čísla s plovoucí desetinnou čárkou se zapisují v mantisovém tvaru (tedy celé číslo + n mocnina 10). Pouze procesor s nimi nepočítá úplně přesně a dokonce procesor od procesoru může hodit mírně odlišný výsledek na stejné operaci s floaty.
Řešení je prostější než prosté, každé float číslo nejdříve zaokrouhlit na zvolenou přesnost, než ho předhodím uživateli na výstup, a nepoužívat floaty tam, kde to není potřeba (např. cenu výrobku raději ukládat v haléřích jako INT než v korunách jako FLOAT, pokud vím, že v cenách budou haléře figurovat).
Mimochodem, -5.5E-17 = 0,00000000000000055, takže po zaokrouhlení už na 16 desetinných míst dostaneš požadovanou nulu :)
_es
Profil
AM_
Pokud vím, čísla s plovoucí desetinnou čárkou se zapisují v mantisovém tvaru (tedy celé číslo + n mocnina 10)

Áno, ale to "celé číslo", aj to "n" je buď v desiatkovej, alebo v dvojkovej sústave (vtedy je to n krát mocnina 2).
Len som sa to snažil zjednodušene Anonymnímu vysvetliť.
Riešením je skôr zaokrúhliť až výsledok, nie medzivýpočty, lebo by tým mohli vzniknúť ďalšie chyby.
AM_
Profil
Riešením je skôr zaokrúhliť až výsledok, nie medzivýpočty, lebo by tým mohli vzniknúť ďalšie chyby.
ano, přesně tak jsem to psal, zaokrouhlit ho předtím, než ho vypíšu uživateli. Pokud ho někam ukládám, chci s ním dál pracovat nebo cokoliv, tak samozřejmě není potřeba.
Jen jsem chtěl říct, že důvod nepřesnosti není v převodu mezi soustavami...
_es
Profil
AM_
Jen jsem chtěl říct, že důvod nepřesnosti není v převodu mezi soustavami...
Ale čiastočne je, zlomok 3/10 sa dá v desiatkovej sústave zapísať presne ako 0.3
No v dvojkovej sa presne zapísať nedá: 0.01001100110011...
Podobne sa aj v desiatkovej sústave nedá presne zapísať napríklad 1/7: 0.142857142857...
Joker
Profil
AM:
Pouze procesor s nimi nepočítá úplně přesně a dokonce procesor od procesoru může hodit mírně odlišný výsledek na stejné operaci s floaty.
To se mi nezdá. Instrukce jsou snad jasně definované a tátáž instrukce s týmiž operandy musí snad dát tentýž výsledek.
Problém je s pamětí, respektive uložením čísel do paměti.

Už to tu bylo zmíněné: Dejme tomu, že do paměti můžete uložit 5 desetinných míst. Je zřejmé, že jakékoliv číslo s víc než 5 desetinnými místy se bude muset nahradit nejbližším číslem s 5 desetinnými místy. Následně vzniká ten problém, že bude vycházet: 1/3 = 0,33333, 3*1/3 = 0,99999, 1 - (3*1/3) = 0,00001
Mimochodem to má ještě další následek- násobení přestane být asociativní operace. Například 4*0,00001*0,25 a 0,25*0,00001*4 nedá stejný výsledek.

Počítač má přesně tenhle problém, jenom má paměť ve dvojkové soustavě a vzhledem ke způsobu uložení reálných čísel musí aproximovat i čísla, u kterých to my zvyklí na desítkovou soustavu neočekáváme.
Kalkulačky tohle řeší jednoduše, pro interní výpočty mají o 2 desetinná místa vyšší přesnost, než zobrazují na displeji, a výsledky prostě zaokrouhlí.
U počítače to je na programátorovi.
AM_
Profil
Ale čiastočne je, zlomok 3/10 sa dá v desiatkovej sústave zapísať presne ako 0.3
v mantisovém zápisu, který float používá, se to uloží jako 3*10^-1. Které z těchto čísel nelze zapsat v binárce přesně? 3, nebo -1?
Jasně, máš pravdu, že v binárce nelze zapsat konečným počtem desetinných (nebo vlastně dvojkynných? :) )míst čísla, u kterých to lze v desítkové soustavě. Ale mantisový zápis je vyjádření desetinného čísla pomocí 2 celých (mantisa a exponent 10).

Joker
To se mi nezdá.
ale je to tak, několikrát jsem o tom četl a praxe o tom svědčí - operace na floatech nejsou přesné.
_es
Profil
AM_
Pokiaľ viem, tak sa používa väčšinou formát z C známy ako double Wikipedia: Double precision floating-point format
A ten mantisový zápis býva teoreticky v tvare x * 2 ^ y, pričom x je v intervale <-1 , 1> a y je celé číslo.
V tom odkaze je zobrazená aj tá 1/3.
_es
Profil
AM_
v mantisovém zápisu, který float používá, se to uloží jako 3*10^-1
Ak by sa aj použil mantisový zápis s celým x, ono to je vlastne jedno, tak 0,3 pomocou celých čísel x a y vo formáte (x * (2 ^ y)) nikdy presne nezapíšeš.
Alebo inak: nájdi riešenie pre celé čísla x a y rovnice (základ 2):
x * (2 ^ y) = 3/10  // nemá riešenie v celých číslách
alebo rovnice (základ 10):
x * (10 ^ y) = 3/10  // má riešenie v celých číslách: x = 3, y = -1

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0