Hallo,
ich muss cm ins inch umwandeln (kein problem), aber es entsteht ein Problem dabei, die Inch-Zahl ist ca. 10 Stellig nach dem Komma. Ich braucher aber 2 Stellen vor, und 2 Stellen nach dem Komma.
Wie kürze ich diese Zahl, mit Verbindung von JavaScript. Die cm-Zahl ist dynamisch, bewegt sich zwischen 160cm und 190cm.
Wenn Dir kleinere Probleme beim Runden egal sind (es gibt bei Float-Zahlen prinzipiell einige Dinge, die anders reagieren, als bei Dezimalzahlen - und das irgendwie "hinzubiegen" ist alles andere als trivial), dann kannst Du das Math-Objekt um eine Funktion erweitern:
Math.roundToPlaces = function (number, places) {
var p = Math.pow(10, places);
var f = number * p;
if (f >= 0.0) {
f = Math.floor(f + 0.5);
} else {
f = Math.ceil(f - 0.5);
}
f = f / p;
if (isFinite(f)) {
return f;
} else {
return number;
}
};
Das rundet Dir arithmetisch, d.h. 0.5 immer zur nächsthöheren Zahl. Du kannst aber z.B. auch Banker's Rounding verwenden, dann nutze Math.round():
Math.roundToPlaces = function (number, places) {
var p = Math.pow(10, places);
var f = number * p;
f = Math.round(f);
f = f / p;
if (isFinite(f)) {
return f;
} else {
return number;
}
};
Auf Grund der oben erwähnten Probleme funktioniert das aber nicht immer genau so, wie erwartet:
Math.roundToPlaces(1.255, 2) -> gibt 1.25 obwohl man mit *beiden*
Verfahren
Ich habe mich vor einiger Zeit mal mit dem Thema "Runden" intensiver auseinandergesetzt und ein RFC geschrieben, wie PHPs round()-Funktion verbessert werden kann (die bisherige Implementierung entspricht meiner obigen). Mein Vorschlag ist hier zu sehen: http://wiki.php.net/rfc/rounding, dort auch mit allen möglichen teils komplizierten Erklärungen.
Ich habe den Algorithmus mal nach Javascript portiert (ist nicht besonders effizient, funktioniert aber):
(function () {
Math.ROUND_MODE_HALF_UP = 1;
Math.ROUND_MODE_HALF_DOWN = 2;
Math.ROUND_MODE_HALF_EVEN = 3;
Math.ROUND_MODE_HALF_ODD = 4;
var roundHelper = function (value, mode) {
var tmp_value;
if (value >= 0.0) {
tmp_value = Math.floor(value + 0.5);
if ((mode == Math.ROUND_MODE_HALF_DOWN && value == (-0.5 + tmp_value)) ||
(mode == Math.ROUND_MODE_HALF_EVEN && value == (0.5 + 2 * Math.floor(tmp_value/2.0))) ||
(mode == Math.ROUND_MODE_HALF_ODD && value == (0.5 + 2 * Math.floor(tmp_value/2.0) - 1.0)))
{
tmp_value -= 1.0;
}
} else {
tmp_value = Math.ceil(value - 0.5);
if ((mode == Math.ROUND_MODE_HALF_DOWN && value == (0.5 + tmp_value)) ||
(mode == Math.ROUND_MODE_HALF_EVEN && value == (-0.5 + 2 * Math.ceil(tmp_value/2.0))) ||
(mode == Math.ROUND_MODE_HALF_ODD && value == (-0.5 + 2 * Math.ceil(tmp_value/2.0) + 1.0)))
{
tmp_value += 1.0;
}
}
return tmp_value;
};
Math.roundToPlaces = function (value, places, mode) {
if (typeof(places) == 'undefined') places = 0;
if (typeof(mode) == 'undefined') mode = Math.ROUND_MODE_HALF_UP;
var f1, f2;
var precision_places = 14 - Math.floor(Math.log(Math.abs(value))/Math.LN10);
f1 = Math.pow(10.0, Math.abs(places));
if (precision_places > places && precision_places - places < 15) {
f2 = Math.pow(10.0, Math.abs(precision_places));
if (precision_places >= 0) {
tmp_value = value * f2;
} else {
tmp_value = value / f2;
}
tmp_value = roundHelper(tmp_value, mode);
f2 = Math.pow(10.0, Math.abs(places - precision_places));
// places < precision_places
tmp_value = tmp_value / f2;
} else {
if (places >= 0) {
tmp_value = value * f1;
} else {
tmp_value = value / f1;
}
// rounding not necessary
if (Math.abs(tmp_value) >= 1e15) {
return value;
}
}
tmp_value = roundHelper(tmp_value, mode);
if (Math.abs(places) < 23) {
if (places > 0) {
tmp_value = tmp_value / f1;
} else {
tmp_value = tmp_value * f1;
}
} else {
var str = "" + tmp_value + "e" + (-places);
tmp_value = parseFloat(str);
if (!isFinite(tmp_value)) {
tmp_value = value;
}
}
return tmp_value;
};
})();
Damit solltest Du wie Du es erwartest runden können, d.h. Math.roundToPlaces(1.255, 2) gibt wirklich 1.26 und nicht 1.25 etc.
Viele Grüße,
Christian