• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

bardzo mała liczba, a nieskończony ułamek w js

Object Storage Arubacloud
0 głosów
626 wizyt
pytanie zadane 19 lutego 2020 w JavaScript przez Pytajnikowiec Początkujący (290 p.)
Cześć, jest sposób, żeby rozróżnić liczbę która jest wynikiem odejmowania np. 0.000000000000000001, a liczbę która jest wynikiem z dzielenia np. 0.(3) -> 0.3333333333333333333333333333333333 -> 0.3333333333334 lub 123.(456) -> 123.456456456456456456 -> 123.45645645646 w javascript?

Nie mam pomysłu jak to zrobić. Na nieskończonym ułamku nie chce wykonywać żadnych zmian, a na bardzo małej liczbie która ma więcej niż 9 liczb po przecinku wykonać .toPrecision(9) lub po prostu .toFixed(9)... w sumie w tej chwili nie istotne.
komentarz 19 lutego 2020 przez Pytajnikowiec Początkujący (290 p.)
Albo jeszcze inaczej. Odejmuję dwie liczby i wychodzi np. 0.3333333333333333333333, ale jest to liczba skończona mająca po prostu dużo cyfr po przecinku, ale już dzielenie 1/3 daje 0.333333333333333333333333 tylko "3" jest " w nieskończoność", więc js upraszcza to do 0.3333333333333334. Mechanizm upraszczania u mnie nie występuje ze względu na sposób działania (wszystkie "obliczenia" są na napisach) i kiedy mogę przerwać skrypt będąc 100% pewnym, że jest to ułamek nieskończony?

1 odpowiedź

+2 głosów
odpowiedź 21 lutego 2020 przez Sebastian Fojcik Nałogowiec (43,020 p.)
edycja 21 lutego 2020 przez Sebastian Fojcik

Jeśli chodzi o tę czwórkę na końcu reprezentacji 0.(3). Liczba z nieskończonym rozwinięciem, np. 0.(3) jest reprezentowana w standardzie IEEE-754, który oczywiście ma do dyspozycji skończoną liczbę bitów (a zatem precyzję). Czwórka na końcu reprezentacji 0.(3) wynika z zaokrąglenia, ale uwaga, nie z zaokrąglenia w systemie dziesiętnym (wtedy 3 zaokrągliłoby się do 0), tylko binarnym.

Nie wiem co dokładnie chcesz zrobić, bo swój problem opisałeś bardzo zawile. Z treści komentarza wydaje mi się, że implementujesz swój (własny?) algorytm dzielenia liczb, które przechowujesz jako napisy(?) i zastanawiasz się kiedy przerwać dzielenie i uznać, że wyszła liczba z nieskończonym rozwinięciem? Jeśli tak, to odpowiedź byłaby taka:

W systemie binarnym:

  • Dodawanie dwóch skończonych liczb zawsze da wynik skończony.
  • Odejmowanie dwóch skończonych liczb zawsze da wynik skończony.
  • Mnożenie dwóch skończonych liczb zawsze da wynik skończony;
  • Dzielenie dwóch liczb (a/b) daje wynik skończony pod warunkiem, że jedyne czynniki pierwsze mianownika b to 2 i 5.

Innymi słowy, przy dzieleniu mając dwie liczby a i b, musisz rozłożyć mianownik b na czynniki pierwsze i sprawdzić, czy jedynymi czynnikami pierwszymi są 2 i 5. Np. 14 = 2 * 7 (czynnikiem pierwszym jest 7, więc ułamek z liczbą 14 w mianowniku będzie miał nieskończone rozwinięcie)

UWAGA!
Oczywiście napisałem wyżej, że ułamek z 14 w mianowniku będzie nieskończony, ale ułamek 7/14 = 1/2 = 0.5 ma skończone rozwinięcie. Ułamek przed sprawdzeniem musisz najpierw skrócić. Na szczęście nie jest to trudne. Mianownik po skróceniu przyjmie postać: b_skrocone = b / NWD(a,b)

Jeśli wynik będzie nieskończony, to pozostaje kwestia znalezienia okresu i zapamiętania go (albo ucięcia wyniku to określonej liczby cyfr).

Od razu uprzedzam. Jeśli masz jakąś liczbę, na której wykonałeś jakieś działanie, np. odejmowanie albo dzielenie (nie wiesz co dokładnie) i chcesz się "po fakcie" (po wykonaniu tego działania) dowiedzieć czy było to odejmowanie, czy może dzielenie, to jest to rzecz jasna niemożliwe. Zawsze musisz przed wykonaniem działania podjąć decyzję o tym, czy wynik będzie skończony czy nie.

Jeśli chcesz jakoś oznaczyć, że wynik, który wyszedł jest w rzeczywistości nieskończony, tylko został przez algorytm ucięty, to zrób sobie jakąś klasę i ustaw flagę. To już zależy od Ciebie :-)

komentarz 21 lutego 2020 przez Sebastian Fojcik Nałogowiec (43,020 p.)
edycja 21 lutego 2020 przez Sebastian Fojcik

Było późno, gdy pisałem powyższą odpowiedź i nie do końca przemyślałem warunek nieskończonego rozwinięcia wyniku dzielenia.

Poprawna odpowiedź:

Wynik dzielenia a/b ma skończone rozwinięcie dziesiętne (i binarne), gdy jedyne dzielniki mianownika to 2 i 5. Innymi słowy, gdy mianownik jest złożony z iloczynu liczb 2 i 5, np.
8 = 2 * 2 * 2
20 = 2 * 2 * 5

Wtedy ułamki 1/51/81/20, itd. będą miały skończone rozwinięcie. Musisz rozłożyć mianownik na czynniki pierwsze i sprawdzić czy jedyne takie czynniki, to 2 i 5.

Popełniłem błąd, bo próbowałem sam wymyślić rozwiązanie, które na pierwszy rzut rozumu wydawało się prawidłowe, a powinienem od razu zajrzeć do rzetelnych źródeł wiedzy. 

Tutaj ciekawy wpis na temat skończoności i nieskończoności rozwinięcia liczb:
http://www.onemathematicalcat.org/algebra_book/online_problems/finite_or_inf_rep.htm

EDIT:
Już poprawiłem odpowiedź.

komentarz 22 lutego 2020 przez Pytajnikowiec Początkujący (290 p.)
Dziękuję bardzo za odpowiedź. Jestem w trakcie pisania swojego upośledzonego algorytmu w celu pozbycia się wszelkich niedokładności w js na liczbach. Poradziłem sobie na przykład z 0.3-0.2, 2.3+3.4, 0.7*7. Jednak testując dalej kalkulator (tak, robię kalkulator) zauważyłem, że przestaje działać przy bardzo małych i bardzo dużych liczbach typu 0.00001/10 lub 100000000000000000000000*100 (1e+23 * 100), więc doszedłem do wniosku że chce wyeliminować wszelkie automatyzmy języka działające pod spodem i napiszę sobie od zera algorytmy arytmetyczne, dlatego używam napisów. Nie chce żeby liczba pokroju 100000000000000000000000000000000000000 była zamieniana na 1e+38 albo 0.000000000000000000000001 na 1e-24. JA chcę mieć pełną kontrolę co się dzieje z liczbami.

Chyba że robię to niepotrzebnie i istnieje złoty środek na te wszystkie przypadki, o którym nie mam pojęcia, a (może się wygłupię) naszukałem się troszkę.

Podobne pytania

0 głosów
1 odpowiedź 224 wizyt
pytanie zadane 3 stycznia 2023 w C i C++ przez HUBSON2912 Obywatel (1,300 p.)
0 głosów
1 odpowiedź 253 wizyt
pytanie zadane 19 maja 2021 w C i C++ przez ViniVici Początkujący (300 p.)
0 głosów
3 odpowiedzi 1,443 wizyt
pytanie zadane 26 maja 2020 w C i C++ przez Ola_00 Nowicjusz (210 p.)

92,575 zapytań

141,424 odpowiedzi

319,649 komentarzy

61,960 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...