![]() |
![]() |
![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 247 Pomógł: 5 Dołączył: 10.12.2007 Ostrzeżenie: (0%) ![]() ![]() |
Witam, niedawno miałem problem związany z tym, że PHP nie umie liczyć.
Mógłby ktoś wytłumaczyć mi na czym polega problem? Wiem, że to ma związek z floating point i precyzją, ale to są PROSTE działania, max 3 miejsca po przecinku... Załóżmy że mam taki kod
Proszę o podanie jakiegoś powodu dlaczego
ew jak wyświetlić prawdziwą wartość $discount / $price (powinno być 0.7) a pewnie jest (6.9999999999999999999), Oczywiście poradziłem sobie używając bcmath Ten post edytował mimol 31.12.2013, 19:10:34 |
|
|
![]() |
![]()
Post
#2
|
|
![]() Grupa: Zarejestrowani Postów: 3 034 Pomógł: 366 Dołączył: 24.05.2012 Ostrzeżenie: (0%) ![]() ![]() |
no a czemu się dziwisz rzutujesz float na inta, a php to chyba już wszyscy wiedza nie radzi sobie z matematyką jak jego starsi bracia
Bo wynik masz taki: Cytat float(70)
int(69) int(70) |
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 247 Pomógł: 5 Dołączył: 10.12.2007 Ostrzeżenie: (0%) ![]() ![]() |
Proszę czytać uważnie....
"Proszę o podanie jakiegoś powodu dlaczego" (zmiana kolejności wykonywania działań, zmienia liczbę) |
|
|
![]()
Post
#4
|
|
![]() Grupa: Zarejestrowani Postów: 3 034 Pomógł: 366 Dołączył: 24.05.2012 Ostrzeżenie: (0%) ![]() ![]() |
no to Ci dałem powód, php przy którymś miejscu po przecinku się gubi, a ponieważ masz liczbę zmiennoprzecinkową a potem chcesz z niej zrobić całkowitą dlatego zwraca 69 zamiast 70
![]() specjalnie wrzuciłem wynik żebyś zobaczył jakiego typy zwracany jest wynik ![]()
Ten post edytował com 31.12.2013, 19:34:04 |
|
|
![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 1 332 Pomógł: 294 Dołączył: 12.10.2008 Skąd: Olkusz Ostrzeżenie: (0%) ![]() ![]() |
php jest dynamicznie rzutowany trochę dla wygody... wykonaj kilka operacji matematycznych na różnych typach liczb np. w c++ oraz wykonaj kilka rzutowan w trakcie, spróbuj zrozumieć gdzie tracisz precyzję to zrozumiesz gdzie problem i nie będziesz zaprzagal do obliczeń kobyly tam gdzie nie ma takiej potrzeby...
-------------------- Jeśli twoja ręka rusza do przodu powstrzymaj swój gniew; gdy wyprzedza cię twój gniew - wycofaj rękę.
|
|
|
![]()
Post
#6
|
|
![]() Grupa: Zarejestrowani Postów: 3 034 Pomógł: 366 Dołączył: 24.05.2012 Ostrzeżenie: (0%) ![]() ![]() |
polecam ten materiał http://gynvael.coldwind.pl/?id=492
![]() |
|
|
![]()
Post
#7
|
|
![]() Grupa: Zarejestrowani Postów: 374 Pomógł: 79 Dołączył: 6.04.2010 Skąd: Ostrów Wielkopolski Ostrzeżenie: (0%) ![]() ![]() |
Magia dzieje się już tutaj:
Zobacz, co wyświetla
Fajne, no nie? ![]() Wyjaśnienie tego zjawiska jest tutaj: http://docs.oracle.com/cd/E19957-01/806-35...g_goldberg.html (nie proś mnie o streszczenie ![]() Sposób radzenia sobie z operacjami arytmetycznymi na liczbach zmiennoprzecinkowych tutaj: http://php.net/types.float (w czerwonej ramce). |
|
|
![]()
Post
#8
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Cytat Wiem, że to ma związek z floating point i precyzją, ale to są PROSTE działania, max 3 miejsca po przecinku... Nie chodzi o liczbę cyfr po przecinku, a o możliwość ich zapisania bez utraty dokładności. I tak 0,1 zostanie zapisane z utratą danych, a 0,5 zostanie zapisane bez utraty danych mimo iż obie mają ledwie jedną cyfrę po przecinku.Zmiana kolejności wykonywania działań sprawia, że inna ilość danych jest tracona na innym etapie co ma wpływ na końcowy wynik. Cytat Oczywiście poradziłem sobie używając bcmath Niepotrzebnie zaprzęgasz tutaj BC Math, skorzystaj ze zwykłego round.
Ten post edytował Crozin 1.01.2014, 23:48:49 |
|
|
![]()
Post
#9
|
|
Grupa: Zarejestrowani Postów: 395 Pomógł: 80 Dołączył: 24.08.2009 Ostrzeżenie: (0%) ![]() ![]() |
Mały offtop odnośnie złego PHP które nawet nie potrafi poprawnie liczyć:
Python też "nie potrafi" liczyć poprawnie: Kod price = 24.5
discount_price = 7.35 discount = price - discount_price offer_value = 100 * discount / price print(offer_value) # 69.999999999.... print(int(offer_value)) # 69 offer_value = 100 * ( discount / price ) print(int(offer_value)) # 70 -------------------- |
|
|
![]()
Post
#10
|
|
Grupa: Zarejestrowani Postów: 247 Pomógł: 5 Dołączył: 10.12.2007 Ostrzeżenie: (0%) ![]() ![]() |
Ktoś wyjaśni skad to się bierze? Dlaczego 14 jest magiczna? |
|
|
![]()
Post
#11
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Nie jest żadną magiczną liczbą. Popatrz sobie na dokładne wartości liczbowe i ilość dziewiątek po przecinku: http://ideone.com/Bfdmye
|
|
|
![]()
Post
#12
|
|
![]() Grupa: Zarejestrowani Postów: 374 Pomógł: 79 Dołączył: 6.04.2010 Skąd: Ostrów Wielkopolski Ostrzeżenie: (0%) ![]() ![]() |
Nie jest żadną magiczną liczbą. Popatrz sobie na dokładne wartości liczbowe i ilość dziewiątek po przecinku: http://ideone.com/Bfdmye Dokładnie. To wynika z zaokrąglania pełnej wartości przechowywanej w pamięci. Nie wiem jaka dokładnie jest precyzja wartości przechowywanej w pamięci, ale przy 50 cyfrach po przecinku:
Zostawiając tylko 14 cyfr dostaniemy: Kod 69.99999999999998 co zostanie wyświetlone z zaokrągleniem ostatniej 8 do 9, bo kolejna cyfra to 5 (czyli zaokrąglenie w górę). Przy 13 miejscach po przecinku Kod 69.9999999999999 co zostanie wyświetlone z zaokrągleniem ostatniej 9 do 0, bo kolejna cyfra to 8 (czyli zaokrąglenie w górę). Zamiana ostatniej cyfry znaczącej na 0 spowoduje łańcuch takich samych zaokrągleń powodujący wyświetlenie tej liczby jako 70,0000000000000. |
|
|
![]() ![]() |
![]() |
Aktualny czas: 19.08.2025 - 10:14 |