• 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

VPS Starter Arubacloud
0 głosów
753 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,040 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,040 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ź 313 wizyt
pytanie zadane 3 stycznia 2023 w C i C++ przez HUBSON2912 Obywatel (1,410 p.)
0 głosów
1 odpowiedź 268 wizyt
pytanie zadane 19 maja 2021 w C i C++ przez ViniVici Początkujący (300 p.)
0 głosów
3 odpowiedzi 1,641 wizyt
pytanie zadane 26 maja 2020 w C i C++ przez Ola_00 Nowicjusz (210 p.)

92,963 zapytań

141,928 odpowiedzi

321,161 komentarzy

62,297 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.

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...