JavaScript Sehr kleiner Dezimalzahlen runden

Fastel

Cadet 4th Year
Registriert
Aug. 2009
Beiträge
73
Hallo. Eine schnelle kurze Frage:
Wir sind in Javascript. Ich habe eine Rechnung mit n Nullen hinter dem Komma.
Bsp A: 0.00000024594126
Bsp B: 0.035412

Gibt es eine gebräuchliche Methode um so zu runden, dass die ersten zwei relevanten Zahlen übrig bleiben?

Bsp A: 0.00000025
Bsp B: 0.035

Der AI Bot sagt, dass es nicht geht, schlägt diesen Weg vor. Aber da brauche ich ja wieder die Informationen, wieviele 0en ich habe, bevor eine erste zahl nicht 0 ist:
Javascript:
function roundToRelevantDigits(number, digits) {
    const rounded = Math.round(number * Math.pow(10, digits)) / Math.pow(10, digits);
    return rounded;
  }

const exampleA = 0.00000024594126;
const roundedA = roundToRelevantDigits(exampleA,8);
console.log(roundedA); // Ausgabe: 0.00000025

const exampleB = 0.035412;
const roundedB = roundToRelevantDigits(exampleB, 2);
console.log(roundedB); // Ausgabe: 0.035

Mit anderen Worten: das geht nicht?
 
Mit nem log10 bekommst du die relevante Stelle. Plus ein Offset drauf, dann kannst du auf deine gewünschte Stelle runden. Eine Suche nach "find first non zero digit" hätte dir das Ergebnis aber auch so gegeben. Dazu brauchts keine "KI".
 
  • Gefällt mir
Reaktionen: BeBur und sh.
Es genügt auch eine einfache Schleife. E: Also, so lange *= 10; rechnen, bis der Wert >= 10 und < 100 ist.
 
CyborgBeta schrieb:
Es genügt auch eine einfache Schleife. E: Also, so lange *= 10; rechnen, bis der Wert >= 10 und < 100 ist.
Das ist ja auch nur wie von Yuuri vorgeschlagen der Logarithmus für Arme ;)

Javascript:
function relevantDigit(num) {
  let digits = Math.floor(-1*Math.log10(num)) + 2;
  // return Math.round(num * Math.pow(10, digits)) / Math.pow(10, digits);
  return Number.parseFloat(num).toFixed(digits);
}

const exampleA = 0.00000024594126;
console.log(relevantDigit(exampleA));
const exampleB = 0.035412;
console.log(relevantDigit(exampleB));

So ist es Text, mit der kommentierten Zeile eine Zahl (wird dann aber als 2.5e-7 geprintet)
 
  • Gefällt mir
Reaktionen: BeBur
Toms schrieb:
Versuchs mal mit der toFixed() Methode :)
Was genau soll deine Lösung machen? Es geht hier nicht um 2 Nachkommastellen, sondern um die ersten zwei Ziffern, die nicht 0 sind.
Ok, der TE hat natürlich auch den falschen Begriff Zahl statt Ziffer benutzt. Im englischen hat er im Code aber immerhin Digit schon von chatgpt bekommen.
 
floq0r schrieb:
Das gilt überall und in jeder Programmiersprache, wo nicht extra noch einen Wrapper um Fließkommazahlen gebaut wurde und wenn irgendwo float steht sollte man immer erstmal davon ausgehen, dass das nicht geschehen ist. Das praktische ist hier zumindest, dass der TE an Zahlen Nahe 0 interessiert ist, das ist der Bereich wo Fließkommazahlen die höchste Genauigkeit haben. Ob einfache Genauigkeit ausreicht weiß nur der TE, an seiner Stelle würde ich hier aber vorsichtshalber mit doppelter Genauigkeit arbeiten, wenn man schon über sowas wie der TE nachdenken muss.
Eine weitere Lösung für das Problem (gibt natürlich etliche) bestünde darin, sich die Zahlen in wissenschaftlicher Notation ausgeben zu lassen. Es gibt auch Notationen bei denen die Mantisse stets Null beträgt.
 
Zuletzt bearbeitet:
@CyborgBeta Kann gut sein, dass es hier egal ist, bin mir grad nicht so ganz sicher. Meine vorherige Aussage war glaube ich auch schon falsch. Freitag Abend :D.
 
Zuletzt bearbeitet:
Nimm dir ein Bier und chill. ;) Das reduziert Fehleinschätzungen. :evillol: Schönes Wochenende.
 
@floq0r und @BeBur Ihr hattet beide recht. Ab Float-Werten kleiner als ca. 0.00001... ist das Ergebnis der Rückrichtung (die Umkehrung der Funktion) nicht mehr genau:

Javascript:
function scaleUp(val) {
  let i = 0;
  while (val < 10) {
    i++;
    val *= 10;
  }
  return [val, i];
}

function scaleDown(valArr) {
  let v = valArr[0];
  for (let i = 0; i < valArr[1]; i++) {
    v /= 10;
  }
  return v;
}

function test(fval) {
  let va = scaleUp(fval);
  let v = scaleDown(va);
  console.log(fval, va, v);
  if (fval !== v) {
    console.error(fval, va, v);
    throw new Error("NE!!!");
  }
}

for (let i = 0; i <= 10; i++) {
  let r = Math.random() / Math.pow(10, i);
  test(r);
}

Code:
0.5577736237779558, [55.777362377795576, 2], 0.5577736237779558
0.01310318680413971, [13.10318680413971, 3], 0.01310318680413971
0.0027554995039847253, [27.554995039847256, 4], 0.0027554995039847253
0.00013449799207196068, [13.449799207196069, 5], 0.00013449799207196068
0.000034480316857154306, [34.48031685715431, 6], 0.000034480316857154306
0.0000010906604148513344, [10.906604148513342, 7], 0.000001090660414851334
Error: NE!!!

https://jsfiddle.net/zmx03cve/
 
Zurück
Oben