Zaokrąglenie nie działa po konwersji

0

Napisałem prosty kalkulator procentów (kalkulatorprocentow.pl), w którym użyłem zaokrąglania do dwóch miejsc po przecinku, ale niestety nie działa to tak jak powinno:

Funkcja zaokrąglania:

function roundTo(n, digits) {
  var negative = false;
  if (digits === undefined) {
    digits = 0;
  }
  if (n < 0) {
    negative = true;
    n = n * -1;
  }
  var multiplicator = Math.pow(10, digits);
  n = parseFloat((n * multiplicator).toFixed(11));
  n = (Math.round(n) / multiplicator).toFixed(digits);
  if (negative) {
    n = (n * -1).toFixed(digits);
  }
  return n;
}

Funkcja do obliczenia zmiany procentowej liczby:

function changeNumberCalculation() {
  var firstNumber = document.getElementById("firstNumber").value;
  var secondNumber = document.getElementById("secondNumber").value;
  var changeNumbeResult = ((secondNumber / firstNumber) - 1)
  var fixedchangeNumbeResult = roundTo(changeNumbeResult, 4);
  if (Number.isNaN(changeNumbeResult)) {
    document.getElementById("changeNumberCalculation").className = "result alert alert-warning"
    document.getElementById("changeNumberCalculation").innerHTML = "Wpisz dane";
  } else {
    document.getElementById("changeNumberCalculation").className = "result alert alert-success"
    document.getElementById("changeNumberCalculation").innerHTML = fixedchangeNumbeResult * 100 + " %";
  }
}

Dla danych firstNumber = 12122134124124124 i secondNumber = 2231131213123123 wynik wychodzi -81.58999999999999, a powinien -81.59

1

Musisz zrozumieć liczby zmiennoprzecinkowe. (Wikipedia -> j/w)
edit: Są zaimplementowane binarnie, dwójkowo

Mają dwa generalne problemy:

  • ograniczoną dokładność (zwykle to jakoś kumają programiści, acz nie zawsze idealnie)
  • problem reprezentacji -> nie każda liczba istnieje, jak na przykład nie istnieje doskonały (binarny) odpowiednik obliczenia 7/3. Problem jest znacznie rzadziej rozumiany.

W JavaScripcie RoundTo NADAL ZWRACA co ??? Zmienny przecinek ...
Obrazowo możesz sobie wyobrazić (bo mi się nie chce sprawdzać), że dziesiętne 81.59 nie istnieje w dziedzinie liczb z.p. dwójkowych

W korpo-językach by się używało typu liczbowego stałoprzecinkowego, którego JS nie ma

0

Możesz użyć https://www.w3schools.com/jsref/jsref_toprecision.asp

var fixedchangeNumbeResult =changeNumbeResult.toPrecision(4);
2

Jakieś to twoje zaokrąglanie przekombinowane. Nie możesz jak każdy prawdziwy programista sprawdzić odpowiedź na stackoverflow :)?

Czyli coś takiego

function roundTo(n, digits = 0) {
	return Math.round((n + Number.EPSILON) * (10 ** digits)) / (10 ** digits);
}

Cały skrypt na szybko napisałem na JSFiddle. Zrobiłem też tam sprawdzenie czy druga liczba nie jest przypadkiem zerem, bo w twoim kodzie tego brakuje (liczba / 0 zwraca Infinity, a nie NaN.

Mój kod zwraca liczby po przecinku kiedy ma to sens, na przykład jeśli rezultatem jest liczba 10, to zwróci 10 a nie 10.00. Jeśli koniecznie chcesz mieć ileś tam miejsc po przecinku niezależnie od wyniku, to możesz użyć toFixed na samym końcu (przy wyświetleniu wyniku).

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