Nie przeczytałem artykułu (tylko przejrzałem), ale to jest oczywisty problem dla każdego kto skończył jakiś sensowny kurs podstaw informatyki... Ale zaraz znajdą się specjaliści developerzy za 15k z polskiego rynku pracy, którzy stwierdzą, że ta wiedza jest niepotrzebna i w ogóle nie warto się tego uczyć, bo na frontendzie też można zarobić 15k.
@GwnBrz: nie, nie jest to oczywisty problem. Wększośc obecnych devów ma zerowe pojęcie o tym co dzieje się "pod spodem" i w 99% zakręciliby petlą. A tak po przeczytaniu przynajmniej będa wiedzieć że coś tu się czai jeśli kiedykolwiek przyjdzie im coś większego na floatach robić.
Mówiąc krótko, z matematycznego punktu widzenia IEEE-754 to koszmar. Najprostsze operacje takie jak dodawanie nie są łączne, rozłączność mnożenia względem dodawanie także nie istnieje. W praktycznych zastosowaniach dużym problemem jest akumulacja błędu po wielu iteracjach.
@wolodia: tak. Ale alternatywe dla liczb zmiennoprzecinkowych znasz? Standard ten obejmuje foata, double i quadruple, ale tego ostatniego używa się tylko kiedy istnieje realna potrzeba, np wściekle dokładne symulacje fizyczne. Double jest w znakomitej wiekszości wystarczający.
Ja wiem, że czasem implementuje się typ decimal. Jest to wartość liczbowa zapisana stringiem. Zastosowanie - głównie w finansach. Liczy się to powoli, ale precyzja jest zachowana.
@blazejzet Koleś 2-3x pisze "jednocześnie wiemy, że działania na zmiennoprzecinkowych liczbach są obarczone błędem". Nie, nie wiedziałem o tym jako laik programistyczny. Jaki błąd? Skąd wynika? Nie wyjaśnił tego a teraz mnie to zastanawia :(
@vladek: z tego samego powodu że ułamek 1/3 w reprezentacji dziesietnej to 0.3333333 tak samo w systemie dwojkowym nie da się normalnie reprezentować części ułamkowej
tak samo w systemie dwojkowym nie da się normalnie reprezentować części ułamkowej
@tomasz-piechura: Oczywiście, że się da. Ale nie każdą. Na przykład liczbę 0.5 zapiszesz bezbłędnie. Tak samo liczby całkowite.
Zapis liczby w dowolnym systemie (binarnym, dziesiętnym, szesnastkowym) to suma każdej jej cyfry pomnożonej przez podstawę systemu (2, 10, 16) podniesioną do potęgi o numerze pozycji danej cyfry (pozycje numerowane od 0, począwszy od pozycji najmniej znaczącej (czyli o najmniejszej wartości)).
To ja mam inne zadanie dla programistów 15k. Załóżmy że mamy ogromny zbiór liczb typu int, i chcemy policzyć jego średnią. Jedyny problem jest taki, że ten zbiór jest na tyle duży, że zwykłe sumowanie i dzielenie przez ilość elementów przekroczy maksymalną wartość możliwą do przypisania intowi. Jak obliczyć średnią z jak najmniejszym błędem? Użycie większych intów (long itp.) odpada.
@Hiranus: Map, reduce lub dziel i rzadź. Liczysz średnią że średnich że średnich itd aż dojdziesz do średniej z powiedzmy 2 elementów co możesz zrobić na intach z przesunięciem bitowym zamiast dzielenia.
Szkoda tylko, że gość tak bezrefleksyjnie podchodzi do rozwiązania rekurencyjnego - jakby stos był czymś kompletnie teoretycznym i miał nieskończoną wielkość. A zaraz po tym chwali się robieniem softu na Arduino :(
@Uszy_bobaka: ale po cholerę koło rewynajdywać? from decimal import *, i używać jako floata. Nie ma problemu z zakresem, nie ma problemu kumulacji błedu zmiennoprzecinkowego.
@tamtokontojuzusunalem: Kurna racja pomroczność jasna, za dużo mi tych pozycji dziesiętnych wychodziło, ale nie sprawdzałem, bo cyfry znaczące się zgadzały... Coś tam wcześniej wcześniej kombinowałem i te ekstra '0' zostały >(
A wynik -> float(str(total)[:-1022]+'.'+str(total)[-1022:]) i heja - będzie Overflow albo nie będzie.
To jest taki mały dowód na to, że nie ma idealnego programu. Analiza błędu doprowadziła do wydania poprawki. Tak jest w przypadku każdego systemu, czy finansowego, operacyjnego, czy bazodanowego. Może taka luka nie pozwoli na przejęcie kontroli nad systemem, chociaż kto wie? Nie da się przeanalizować każdego przypadku.
Komentarze (229)
najlepsze
Komentarz usunięty przez moderatora
( ͡° ͜ʖ ͡°)
Ja wiem, że czasem implementuje się typ decimal. Jest to wartość liczbowa zapisana stringiem. Zastosowanie - głównie w finansach. Liczy się to powoli, ale precyzja jest zachowana.
Nie zapisana stringiem, tylko w bazie 10.
@tomasz-piechura: Oczywiście, że się da. Ale nie każdą. Na przykład liczbę 0.5 zapiszesz bezbłędnie. Tak samo liczby całkowite.
Zapis liczby w dowolnym systemie (binarnym, dziesiętnym, szesnastkowym) to suma każdej jej cyfry pomnożonej przez podstawę systemu (2, 10, 16) podniesioną do potęgi o numerze pozycji danej cyfry (pozycje numerowane od 0, począwszy od pozycji najmniej znaczącej (czyli o najmniejszej wartości)).
Komentarz usunięty przez moderatora
#15k
Komentarz usunięty przez moderatora
A tutaj: kolejne rozważania: https://friweb.pl/przeklenstwo-kahana-tanie-zabawy-floatami/
Komentarz usunięty przez moderatora
Komentarz usunięty przez moderatora
To samo tyczy się MySQL gdzie nawet nie ma money.
@ShadowDancer bo wolałes z pytaniem. Dużo na ten temat jest na stackoverflow gdzie będą odniesienia i dokładne wyjaśnienia.
from decimal import *
, i używać jako floata. Nie ma problemu z zakresem, nie ma problemu kumulacji błedu zmiennoprzecinkowego.https://docs.python.org/3/library/decimal.html
A wynik ->
float(str(total)[:-1022]+'.'+str(total)[-1022:])
i heja - będzie Overflow albo nie będzie.