Błędny wynik tangensa

2

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 I sposobie wynik pokazuje błędny 16331239353195370 = 16331239353195370.0000 tangens alfa, a w drugim sposobie -1.995200412208242 = -1.9952. Jeśli użytkownik wprowadzi liczbę 45 stopni to wynik pokazuje poprawny 1 = 1.0000 .

Co zrobić aby po wprowadzeniu liczby 90 stopni pokazał się wynik infinity?
Proszę o pomoc i wskazanie gdzie jest błąd.

HTML

<!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>

I sposób

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 = '';
    
}

II sposób

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

function resetuj () {

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

Wygląda na to, że round i/lub parse nie zachowuje NAN/infinity, co tu gdybać.

6

Witaj w świecie liczb zmiennoprzecinkowych. Pamiętaj że Math.PI to nie liczba PI tylko jest 64 bitowe przybliżenie, a więc już samo wyrażenie Math.PI obarczone jest błędem. Błąd ten po wyliczeniu tangensa ujawnia się potem w wyniku.

Dzielenie / 180 również wprowadzi błąd ze względu na ograniczoną precyzję.

Można to poprawić w głupi sposób czyli mając pewne wartości liczone na sztywno, lub bardziej inteligentnie np. wykrywając asymptoty.

Tangens(90 stopni) w wydaniu kalkulatora apple:
screenshot-20210922092246.png

2

Poguglaj numer 16331239353195370 - ten problem dotyczy wielu środowisk, w tym nawet kalkulatorów.

0

Na stronie http://jsfiddle.net/DanVicBez/j7LER/ wynikiem jest infinity.Jaki kod jest tam odpowiedzialny za to że wynikiem jest infinity?

0

@Marta Długa:

Ten kod, którego nie ma, prawdodpobnie parse.

ps. już Ci to pisałem co analizuję z kodu, ale sprawdzać nie będę

0

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

Nie wiem gdzie mam błąd. Proszę o wskazanie błędu i poprawienie. Niestety dopiero się uczę i jeszcze nie wszystko wiem.

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

0

@Marta Długa: Błagam pomóżcie.

1

Tangens jest funkcją okresową, czyli masz do ogarnięcia tylko parę przypadków.

  • Dla 90 stopni +- 180 w okresie, tangens jest nieznaczony (dzielenie przez zero)
  • Dla 0 stopni +- 180 w okresie, tangens wynosi 0. Nie wiem czy zauważyłaś, ale twój kod przy zerze też pokazuje złe wartości.
  • Dla pozostałych, po prostu liczysz

Więc napisz swoją własną funkcję, na przykład tak:

function tan(deg) {
    if (deg % 90 == 0) {
        if ((deg / 90) % 2 == 0) {
      	    return 0;
        } else {
      	    return undefined;
        }
   }
   return Math.tan(Math.PI / 180 * deg)
}

Co to robi:

  • Sprawdza czy liczba jest podzielna przez 90
  • Jeśli jest, sprawdza czy wynik dzielenia tej liczby przez 90 jest parzysty
    • Jeśli jest, zwraca 0
    • Jeśli nie, zwraca undefined, ale możesz sobie tu wpisać cokolwiek, na przykład nieskończoność, chociaż nie jest to końca poprawne. Bo to jest coś co dąży do nieskończoności, lub minus nieskończoności
  • W przeciwnym wypadku po prostu liczy tego tangensa
Marta Długa napisał(a):

Na stronie http://jsfiddle.net/DanVicBez/j7LER/ wynikiem jest infinity.Jaki kod jest tam odpowiedzialny za to że wynikiem jest infinity?

Tam jest całkiem inny sposób liczenia, w ogóle nie używają wbudowanych funkcji trygonometrycznych.

0

@m31: Coś źle zrobiłam i nie wiem co bo wynik pokazuje function TAN(SA) {
if (SA % 90 == 0) {
if ((SA / 90) % 2 == 0) {
return 0;
} else {
return undefined;
}
}
return Math.tan(Math.PI / 2 * SA);
}.

function oblicz() {
const SA = parseInt(document.getElementById("SA").value);
const TAN = Math.tan(Math.PI / 2 * SA);
     document.getElementById("TAN").innerHTML = function TAN(SA) {
    if (SA % 90 == 0) {
        if ((SA / 90) % 2 == 0) {
            return 0;
        } else {
            return undefined;
        }
   }
   return Math.tan(Math.PI / 2 * SA);
}
}

0

@m31: Błagam o pomoc. Nie wiem co mam źle. Błagam powiedźcie mi gdzie mam błąd.

function oblicz() {
const SA = parseInt(document.getElementById("SA").value);
const SIN = Math.sin(parseInt(SA) * Math.PI / 180);


    document.getElementById("SIN").innerHTML = Math.sin(SA * Math.PI / 180) + ' = ' + SIN.toFixed(4);
   
  function tan(TAN){ 
 if (TAN % SA == 0){
        if ((TAN / SA) % 2 == 0){
        document.getElementById("TAN").innerHTML =  0;
      }
      else{
          document.getElementById("TAN").innerHTML = ' <b>Nie istnieje! - &#8734</b> ';;
      }
    }
    document.getElementById("TAN").innerHTML = Math.tan(Math.PI / 2 * TAN);
 }
}

0

Olaboga, tutaj masz jak to można zrobić Twoim cudacznym sposobem:

function oblicz() {
const SA = parseInt(document.getElementById("SA").value);
const SIN = Math.sin(parseInt(SA) * Math.PI / 180);
const COS = Math.cos(parseInt(SA) * Math.PI / 180);

		document.getElementById("KOS").innerHTML = Math.cos(SA * Math.PI / 180) + ' = ' + COS.toFixed(4);
    document.getElementById("SIN").innerHTML = Math.sin(SA * Math.PI / 180) + ' = ' + SIN.toFixed(4);
    document.getElementById("TAN").innerHTML = typeof tan() === 'number' ? tan() + ' = ' + tan().toFixed(4) : tan();

function tan(){ 
	if (SA % 90 == 0){
        if ((SA / 90) % 2 == 0) {
        return  0;
 }
      else{
          return ' <b>Nie istnieje! - &#8734</b> ';
      }
    }
    return Math.tan(Math.PI / 180 * SA);
 }
}

https://jsfiddle.net/26kLd3pj/1/

A tutaj masz w miarę po ludzku, chociaż jeszcze parę poprawek wymaga (na przykład sprawdzenie czy input jest liczbą), ale mi się nie chce.
https://jsfiddle.net/68pug547/1/

0

@m31: Właśnie analizuje kod mam pytanie.
Zamiast

function roundTo(num, decimalPlaces = 4) {
		return Math.round((num + Number.EPSILON) * (10 ** decimalPlaces)) / (10 ** decimalPlaces);

Nie lepiej jest używać

toFixed(4)

Jest krótszy i bardziej zrozumiały a w dodatku ten sam wynik wychodzi. Mnie uczą na studiach że kod powinien być jak najkrótszy.
Co można użyć zamiast Number.EPSILON?

0
Marta Długa napisał(a):

@m31: Właśnie analizuje kod mam pytanie.

Zamiast

function roundTo(num, decimalPlaces = 4) {
		return Math.round((num + Number.EPSILON) * (10 ** decimalPlaces)) / (10 ** decimalPlaces);

Nie lepiej jest używać

toFixed(4)

Jest krótszy i bardziej zrozumiały a w dodatku ten sam wynik wychodzi. Mnie uczą na studiach że kod powinien być jak najkrótszy.
Co można użyć zamiast Number.EPSILON?

Możesz użyć, toFixed.
Tylko tworzy to potworki w stylu 1.0000, zamiast 1.

A to Number.EPSILION to akurat najmniej istotne w całym tym kodzie. Zapobiega to pewnym rzadkim błędom.
Na przykład Math.round(1.005 * 100) / 100 zwraca błędnie 1, gdy powinno 1.01.
Natomiast taka konstrukcja Math.round((1.005 + Number.EPSILON) * 100) / 100 zwraca już poprawnie 1.01

0

@m31: javascript const deg = parseInt(input.value) DEG to liczba wprowadzana przez użytkownika jak SA?

0

@m31: Ja zrobiłam to trochę inaczej co o tym sądzisz? Czy mogę jeszcze tam gdzieś umieścić javascript Number.EPSILON ale bez obliczeń tak jak to robię tofixed?

<!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 &#186;  &#593; na Sinus &#593;</h3>
            Stopień &#186; &#593; <input type="number" id="SA"><br>
            Sinus &#593;: <span id="SIN">= </span><br><br>
            Cosinus &#593;: <span id="KOS">= </span><br><br>
            Tangens &#593;: <span id="TAN">= </span><br><br>
            <input type="button" value="Oblicz" style="cursor: pointer;" onclick="oblicz()">
            <input type="reset" value="RESETUJ" style="cursor: pointer;" onclick="resetuj()">
        </div>
    </form>

</body>

</html>
function tan(SA) {
  if (SA % 90 == 0) {
    if ((SA / 90) % 2 == 0) {
      return 0;

    } else {
      return ' <b>Nie istnieje! ';
    }

  }
  return Math.tan(Math.PI / 180 * SA).toFixed(4);
}


function oblicz() {
const SA = parseInt(document.getElementById("SA").value);

const TAN = document.getElementById('TAN').value;
document.getElementById('TAN').innerHTML = tan(SA);

const RAD = SA * Math.PI / 180;
const SIN = document.getElementById('SIN').value;
const KOS = document.getElementById('KOS').value;

document.getElementById('SIN').innerHTML = Math.sin(RAD) .toFixed(4);
document.getElementById('KOS').innerHTML = Math.cos(RAD).toFixed(4);

}


function resetuj () {

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

0

Dołączam przelicznik COTANGENS. Pokazuje mi błędny wynik COTANGENSA stopni alfa od 1 do 44 i 90, 270. Co mam źle?

function tan(SA) {
  if (SA % 90 == 0) {
    if ((SA / 90) % 2 == 0) {
      return 0;

    } else {
      return ' <b>Nie istnieje! ';
    }

  }
  return Math.tan(Math.PI / 180 * SA).toFixed(4);
}

function ctg(SA) { 
    return (1 / tan(SA)).toFixed(4); 
}

function oblicz() {
const SA = parseInt(document.getElementById("SA").value);


const TAN = document.getElementById('TAN').value;
document.getElementById('TAN').innerHTML = tan(SA);

const CTAN = document.getElementById('CTAN').value;
document.getElementById('CTAN').innerHTML = ctg(SA);

}

0
Marta Długa napisał(a):

Dołączam przelicznik COTANGENS. Pokazuje mi błędny wynik COTANGENSA stopni alfa od 1 do 44 i 90, 270. Co mam źle?

Od 1 do 44 nie widzę błędu.
Natomiast dla reszty musisz przewidzieć dwa przypadki.
Tam gdzie tangens zwracał 0, tam cotanges będzie zwracał nie istnieje, czy tam nieskończoność. Dzielisz coś przez zero.
A tam gdzie tangens zwracał Nie istnieje, cotangens będzie 0. Dzielisz przez coś, co dąży do nieskończoności.

A tak w ogóle, sama piszesz to tak dla siebie? Czy kampania wrześniowa na uczelni?

0

@m31: Do 44 daje złe wyniki. Co jest źle?

function ctg(SA) {
  if (SA % 90 == 0) {
    if ((SA / 90) % 2 == 0) {
      return ' <b>Nie istnieje! ';

    } else {
      return 0;
    }

  }
  return 1 / tan(SA);
}
4

Pierwsze co to czy rozumiesz co tu się dzieje?

  if (SA % 90 == 0) {
    if ((SA / 90) % 2 == 0) {
      return ' <b>Nie istnieje! ';

    } else {
      return 0;
    }

Ctg ma gdzie indziej asymptoty. Zerknij na wykresy ctg i tg.
Wiesz co to operator modulo - %? Spróbuj to opisać sobie po kolei na kartce i podstaw sobie liczby. W programowaniu jest taka metoda "na kaczuszkę" czy tam "na misia", bierzesz misia i tłumaczysz mu jak działa Twój program linijka po linijce. Pewnie wtedy zobaczysz gdzie jest błąd.

0

Byłam i jestem słaba z matematyki.
SA % 90 == 0 - Reszta z dzielenia SA przez 90 jest porównywane do 0.
SA / 90 - SA dzielone przez 90
SA / 90 % 2 == 0 - Reszta z dzielenia wyniku przez 2 jest porównywane do 0
Czy dobrze opisałam?

0

ctg = 1 / tg
Zgadza się?
Nie wiem gdzie umieścić to 1.

0

Już mi prawie wyszło tylko że jak użytkownik podaje liczbę 1 to wynik pokazuje 0.0175 zamiast -0.0175.

function ctg(SA) {
  if (SA % 90 == 0) {
    if ((SA / 90) % 2 == 0) {
      return ' <b>Nie istnieje! ';

    } else {
      return 0;
    }

  }
  return Math.tan(Math.PI / 180 * SA).toFixed(4);
}

function oblicz() {
const SA = parseInt(document.getElementById("SA").value);

const CTAN = document.getElementById('CTAN').value;
document.getElementById('CTAN').innerHTML = ctg(SA);

}

II sposób jak użytkownik podaje liczbę 1 to wynik pokazuje 57.2900 zamiast -0.0175.

function ctg(SA) {
  if (SA % 90 == 0) {
    if ((SA / 90) % 2 == 0) {
      return ' <b>Nie istnieje! ';

    } else {
      return 0;
    }

  }
  return 1 / (Math.tan(Math.PI / 180 * SA));
}

function oblicz() {
const SA = parseInt(document.getElementById("SA").value);

const CTAN = document.getElementById('CTAN').value;
document.getElementById('CTAN').innerHTML = ctg(SA).toFixed(4);

}
0

@Marta Długa: Pomóżcie błagam nie mam zielonego pojęcia jak to zrobić.

0

Błagam powiedźcie co mam źle.

1

No ale przecież cotangens jednego stopnia to jest w przybliżeniu 57, a nie 0.0175 ani tym bardziej -0.0175.

Skąd ty bierzesz te wartości?

Nawet ctg od jednego radiana to nie jest 0.0175, tylko 0.64.

W tej funkcji

function ctg(SA) {
  if (SA % 90 == 0) {
    if ((SA / 90) % 2 == 0) {
      return ' <b>Nie istnieje! ';

    } else {
      return 0;
    }

  }
  return 1 / (Math.tan(Math.PI / 180 * SA));
}

Nie masz błędu.

1

Marta, jeśli chcesz, żebyśmy to napisali za Ciebie, to pomyliłaś fora. Jeśli zaś chcesz to napisać sama, to mam wrażenie, że brakuje Ci zarówno podstawowych umiejętności programowania (tak bardzo podstawowych, że mylisz przypisanie funkcji z przypisaniem wyniku wywołania funkcji), jak i podstaw trygonometrii. Dokształć się (opanowanie absolutnych podstaw jednego i drugiego dla dorosłego człowieka to kilka dni), wróć, na pewno pomożemy.

0

Wiesz jak zamienić kąt na radiany?

1 użytkowników online, w tym zalogowanych: 0, gości: 1