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

Błędny wynik tangensa Javascript

+1 głos
131 wizyt
pytanie zadane 21 września w JavaScript przez Marta Długa Obywatel (1,660 p.)

Dzień dobry jestem początkująca.

Zrobiłam kalkulator, który przelicza stopnie alfa na sinus alfa, cosinus alfa, tangens alfa. Przy wprowadzeniu liczbę 90 stopni przez użytkownika wynik tangensa powinien pokazać ∞ lub infity lub w miejsce wyniku nic nie powinno być (wynik nie istnieje). Natomiast mi wynik pokazuje błędny 16331239353195370 = 16331239353195370.0000 tangens alfa. Jeśli użytkownik wprowadzi liczbę 45 stopni to wynik pokazuje poprawny 1 = 1.0000 .

Proszę o pomoc i wskazanie gdzie jest błąd.

<!DOCTYPE html>
<html lang="pl">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="stopien_sinus.js"></script>
</head>

<body>
    <form id="oblicz" action="" method="post" autocomplete="off">
        <div>
            <h3>Przelicznik Stopnia Alfa na Sinus Alfa</h3>
            Stopień Alfa <input type="number" id="SA"><br>
            Sinus: <span id="SIN">= </span><br><br>
            Cosinus: <span id="KOS">= </span><br><br>
            Tangens: <span id="TAN">= </span><br><br>
            <input type="button" value="Oblicz" onclick="myFunction()">
            <input type="reset" value="RESETUJ" onclick="resetuj()">
        </div>
    </form>

</body>

</html>

 

function myFunction() {
const SA = parseInt(document.getElementById("SA").value);
const SIN = Math.sin(parseInt(SA) * Math.PI / 180);
const KOS = Math.round(Math.cos(parseInt(SA) * Math.PI / 180));
const TAN = Math.round(Math.tan(parseInt(SA) * Math.PI / 180));
    document.getElementById("SIN").innerHTML = Math.sin(SA * Math.PI / 180) + ' = ' + SIN.toFixed(4);
    document.getElementById("KOS").innerHTML = Math.round(Math.cos(SA * Math.PI / 180)) + ' = ' + KOS.toFixed(4);
    document.getElementById("TAN").innerHTML = Math.round(Math.tan(SA * Math.PI / 180)) + ' = ' + TAN.toFixed(4);
   
return false;
}

function resetuj () {

    document.getElementById("SIN").innerHTML = '';
    document.getElementById("KOS").innerHTML = '';
    document.getElementById("TAN").innerHTML = '';
   
}

 

3 odpowiedzi

+2 głosów
odpowiedź 26 września przez Bosswell Nałogowiec (34,710 p.)
wybrane 26 września przez Marta Długa
 
Najlepsza

Dla przyszłych poszukiwaczy rozwiązanie wyciągnięte z komentarzy.
Przy wyznaczeniu nieskończoności tangensa dla konkretnych stopni, możemy skorzystać z jego okresowości w celu zredukowania stopni.

Dla 400
(int) 400 / 180 = 2
400 - 2 * 180 = 40
--------
Dla 270
(int) 270 / 180 = 1
270 - 1 * 180 = 90
--------
Dla -90
(int) -90 / 180 = 0
-90 - 0 * 180 = -90
--------
Dla -450
(int) -450 / 180 = -2
-450 - (-2 * 180) = -450 + 360 = -90
--------
a = stopnie;
b = parseInt(a / 180);
c = Math.abs(a - b * 180);

if (c === 90) {
   console.log("Brak rozwiązań");
}

Podane przez użytkownika stopnie, redukujemy przez jego okres 180 stopni. Po redukcji, tangens nie będzie miał rozwiązań dla 90 i -90 stopni.

Aplikacja rozwiązania do zadania:

function myFunction() {
  const container = document.getElementById("TAN");
  const deegres = parseInt(
    document.getElementById("SA").value
  );
 
  const normalizedDeegres = Math.abs(
    deegres - parseInt(deegres / 180) * 180
  );
 
  if (normalizedDeegres === 90){
      container.innerHTML = '<b>Nie istnieje! - &#8734</b>';
 
      return;
  }
 
  container.innerHTML = `<b>${Math.tan(deegres)}</b>`;
}

 

+1 głos
odpowiedź 21 września przez edutomek Mądrala (6,340 p.)
Czyli działa (w miarę) poprawnie. Powinno być +inf, jest jakaś bardzo duża liczba.

Po pierwsze - Math.PI to nie jest liczba PI. To jest pewne przybliżenie liczby PI (której dokładnie nie da się zapisać, bo jest to liczba niewymierna). Mamy więc pierwsze źródło błędów numerycznych - operowanie na wartościach przybliżonych.

Wyliczając kąt w radianach nie wyliczymy dokładnie tego PI, PI/2 (innych kątów też nie), lecz jedynie ich pewne przybliżenia.

W zależności od tego, jakie to będą przybliżenia, otrzymamy mniej lub bardziej dokładne wyniki.

Nie wspominając o tym, jak ten tangens jest zaimplementowany. Gdzieś znalazłem informację, że jest to sin(x) / cos(x) - ale jak są zaimplementowane te sinusy i cosinusy? To są jakieś algorytmy numeryczne, a więc wyniki będą przybliżone (czasami lepiej, czasami gorzej) i obarczone błędami numerycznymi.

No i potem takie "kwiatki" wychodzą.

Zresztą nie trzeba funkcji trygonometrycznych, żeby doświadczyć problemów numerycznych: proponuję wpisać w JS a = 0.1, a potem sprawdzić wynik a + a + a (u mnie np. wcale nie wychodzi 0.3; co ciekawe, przy dalszym dodawaniu są poprawne wyniki, ale już przy ośmiu składnikach też nie mam 0.8). Można też popróbować z a = 0.01, a = 0.001... Ciekawskim polecam sprawdzić a = 0.125 i zastanowić się, dlaczego dla tej interesującej wartości akurat wszystko liczone jest poprawnie.

Generalnie, operując na liczbach zmiennoprzecinkowych, należy przyjąć pewną dokładność. Tzn. nie porównujemy wartości zmiennych do stałych, lecz sprawdzamy, czy wartość bezwzględna różnicy jest odpowiednio mała: if ( Math.abs(a - 2) < EPSILON ) ...

Podobnie można postąpić z tymi kątami. Nie wyliczymy dokładnie pewnych wartości (np. tych 45, 90, czy 180 stopni) - to może warto napisać własną funkcję, która dla tych specyficznych wartości (z pewną dokładnością) zwróci poprawny wynik?
komentarz 24 września przez Bosswell Nałogowiec (34,710 p.)
function myFunction() {
  const container = document.getElementById("TAN");
  const deegres = parseInt(
    document.getElementById("SA").value
  );

  const normalizedDeegres = Math.abs(
    deegres - parseInt(deegres / 180) * 180
  );

  if (normalizedDeegres === 90){
      container.innerHTML = '<b>Nie istnieje! - &#8734</b>';

      return;
  }

  container.innerHTML = `<b>${Math.tan(deegres)}</b>`;
}

 

komentarz 25 września przez Marta Długa Obywatel (1,660 p.)
Dzięki. Szczegółowo przeanalizowałam kod i teraz już wiem jak to się robi. Ja właśnie przy robieniu różnych zadań uczę się JavaScript.
komentarz 25 września przez Marta Długa Obywatel (1,660 p.)

@Bosswell, Jak mogę oznaczyć że Twoja odpowiedź jest najlepsza?

komentarz 26 września przez Bosswell Nałogowiec (34,710 p.)
Dodałem nową odpowiedź z podsumowaniem
komentarz 26 września przez Marta Długa Obywatel (1,660 p.)
Dzięki. Zaznaczyłam Twoją odpowiedź jako najlepszą.
0 głosów
odpowiedź 22 września przez Marta Długa Obywatel (1,660 p.)
edycja 24 września przez Marta Długa

POMÓŻCIE BŁAGAM

Po wprowadzeniu liczby 90 stopni pokazuje wynik Nie istnieje ale po wprowadzeniu 45 wynik  też pokazuje Nie istnieje zamiast 1.0000.

Nie wiem gdzie mam błąd. Błagam pomóżcie.

function myFunction() {
const SA = parseInt(document.getElementById("SA").value);
const TAN = Math.abs(parseInt(SA) - (parseInt(SA)  / 180) * 180);
   if (TAN === SA){
        document.getElementById("TAN").innerHTML = Math.abs(SA - (SA / 180) * 180) + '=' + ' <b>Nie istnieje! - &#8734</b> ' + TAN.toFixed(4);
    }
  
function resetuj () {
    document.getElementById("TAN").innerHTML = '';
}

 

komentarz 24 września przez Marta Długa Obywatel (1,660 p.)
Błagam pomóżcie . Nie wiem jak to zrobić. Szukałam i nie znalazłam.

Podobne pytania

0 głosów
1 odpowiedź 53 wizyt
0 głosów
1 odpowiedź 241 wizyt
–1 głos
0 odpowiedzi 75 wizyt
Porady nie od parady
Pytania na temat serwisu SPOJ należy zadawać z odpowiednią kategorią dotyczącą tej strony.SPOJ

85,726 zapytań

134,512 odpowiedzi

298,568 komentarzy

56,634 pasjonatów

Motyw:

Akcja Pajacyk

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

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...