webentwicklung-frage-antwort-db.com.de

Löschen Sie Ziffern nach zwei Dezimalstellen, ohne den Wert zu runden

ich habe einen Wert in PHP-Variable so

$var='2.500000550';
echo $var

ich möchte alle Dezimalstellen nach 2 Ziffern löschen.

wie jetzt wird der Wert der Variablen sein

$var='2.50';
echo $var

denken Sie daran, dass dieser Wert von mysql databse stammt

aber wenn ich round php function benutze, bin ich rund geworden, aber ich brauche nicht rund, ich muss einfach alle Ziffern nach 2 dezimal löschen.

ich habe müde, flot() und viele andere Optionen keinen Erfolg.

Vielen Dank

38
air

TL; DR:

Die PHP native Funktion bcdiv scheint genau das zu tun, was erforderlich ist, und zwar ordnungsgemäß.

Um eine Zahl einfach "abzuschneiden", ist bcdiv($var, 1, 2);, wobei 2 die Anzahl der zu speichernden Dezimalstellen ist (und 1 der Denomenator ist - durch die Division durch 1 können Sie die ursprüngliche Zahl einfach auf die gewünschten Dezimalstellen abschneiden).

Vollständige Antwort (für die Geschichte)

Dies stellt sich als schwieriger heraus, als man denkt.

Nachdem diese Antwort (falsch) ziemlich positiv war, ist mir aufgefallen, dass auch Sprintf rund wird.

Anstatt diese Antwort zu löschen, verwandle ich sie in eine robustere Erklärung/Diskussion jeder vorgeschlagenen Lösung.

number_format - Falsch. (Runden)
Versuchen Sie es mit Zahlenformat :

$var = number_format($var, 2, '.', '');  // Last two parameters are optional
echo $var;
// Outputs 2.50

Wenn Sie möchten, dass es sich um eine Zahl handelt, tippen Sie einfach in einen Float-Typ:

$var = (float)number_format($var, 2, '.', '');

Anmerkung: Wie in den Kommentaren darauf hingewiesen wurde, ist dies round die Zahl.

sprintf - falsch (sprintf auch Runden)
Wenn es nicht wichtig ist, die Zahl zu runden, verwenden Sie sprintf für die Antwort unten.

$var = sprintf("%01.2f", $var);

Boden - nicht ganz! (Boden rundet negative Zahlen) 

floor wird mit etwas Mathe das tun, was Sie wollen:

floor(2.56789 * 100) / 100; // 2.56

Dabei steht 100 für die von Ihnen gewünschte Präzision. Wenn Sie drei Ziffern haben wollten, dann:

floor(2.56789 * 1000) / 1000; // 2.567

Dies hat jedoch ein Problem mit negativen Zahlen. Negative Zahlen werden immer noch gerundet und nicht abgeschnitten:

floor(-2.56789 * 100) / 100; // -2.57

"Alt" Richtige Antwort: Funktion nutzt Etage

Eine absolut robuste Lösung erfordert also eine Funktion:

function truncate_number( $number, $precision = 2) {
    // Zero causes issues, and no need to truncate
    if ( 0 == (int)$number ) {
        return $number;
    }
    // Are we negative?
    $negative = $number / abs($number);
    // Cast the number to a positive to solve rounding
    $number = abs($number);
    // Calculate precision number for dividing / multiplying
    $precision = pow(10, $precision);
    // Run the math, re-applying the negative value to ensure returns correctly negative / positive
    return floor( $number * $precision ) / $precision * $negative;
}

Ergebnisse aus der obigen Funktion:

echo truncate_number(2.56789, 1); // 2.5
echo truncate_number(2.56789);    // 2.56
echo truncate_number(2.56789, 3); // 2.567

echo truncate_number(-2.56789, 1); // -2.5
echo truncate_number(-2.56789);    // -2.56
echo truncate_number(-2.56789, 3); // -2.567

Neue richtige Antwort

Verwenden Sie die native Funktion PHP bcdiv

echo bcdiv(2.56789, 1, 1);  // 2.5
echo bcdiv(2.56789, 1, 2);  // 2.56
echo bcdiv(2.56789, 1, 3);  // 2.567
echo bcdiv(-2.56789, 1, 1); // -2.5
echo bcdiv(-2.56789, 1, 2); // -2.56
echo bcdiv(-2.56789, 1, 3); // -2.567
90
cale_b
floor(2.500000550 * 100) / 100;

Das sollte deine Aufgabe erledigen ...

9
Sujit Agarwal

Sie fordern eine Funktion an, die "2.50" Und nicht 2.5 Zurückgibt, also Sie sprechen nicht von Arithmetik hier aber String-Manipulation =. Dann ist preg_replace Dein Freund:

$truncatedVar = preg_replace('/\.(\d{2}).*/', '.$1', $var);

// "2.500000050" -> "2.50", "2.509" -> "2.50", "-2.509" -> "2.50", "2.5" -> "2.5"

Wenn du es mit Arithmetik machen willst, benutze einfach:

$truncatedVar = round($var * 100) / 100);

// "2.500000050" -> "2.5", "2.599" -> "2.59", "-2.599" -> "2.59"
6
flu

versuchen Sie es mit number_format :

echo number_format('2.50000050', 2); // 2.50
5
matino

number_format rundet die Nummer 

php > echo number_format(128.20512820513, 2)."\n";
128.21

Ich habe preg_replace verwendet, um die Zeichenfolge wirklich zu schneiden

php > echo preg_replace('/(\.\d\d).*/', '$1', 128.20512820513)."\n";
128.20
4
Liphtier

benutze sprintf

sprintf("%01.2f", $var);
3
Aurimas Ličkus

Verwenden Sie die native Funktion PHP bcdiv

Beispiel:

echo bcdiv(3.22871, 1, 1);  // 3.2
echo bcdiv(3.22871, 1, 2);  // 3.22
echo bcdiv(3.22871, 1, 3);  // 3.228
echo bcdiv(-3.22871, 1, 1); // -3.2
echo bcdiv(-3.22871, 1, 2); // -3.22

Für Ihren Fall:

$var='2.500000550';
echo $var
echo bcdiv($var, 1, 2);  // 2.50
2
Faisal

jemand hier gepostet über 

boden (2.500000550 * 100)/100;

function cutAfterDot($number, $afterDot = 2){
$a = $number * pow(10, $afterDot);
$b = floor($a);
$c = pow(10, $afterDot);
echo "a $a, b $b, c $c<br/>";
return $b/$c ;
}
echo cutAfterDot(2.05,2);

a 205, b 204, c 100
2.04

also in roher Form nicht verwenden ....... aber wenn Sie ein wenig Epsilon hinzufügen ...

function cutAfterDot($number, $afterDot = 2){
        return floor($number * pow(10, $afterDot) + 0.00001) / pow(10, $afterDot);
    }

es klappt!

2

Wenn Sie die Zahl nicht runden, aber die Nachkommastellen entfernen möchten, können Sie die Methode "substr" verwenden

substr(string, start, length);
substr(4.96, 0, -1);
0
Fahad Ahmed

boden - nicht ganz! (Boden rundet negative Zahlen) 

Eine mögliche Lösung von cale_b answer.

static public function rateFloor($rate, $decimals)
{

    $div = "1" . str_repeat("0", $decimals);

    if ($rate > 0) {
        return floor($rate * $div) / $div;
    }

    $return = floor(abs($rate) * $div) / $div;

    return -($return);

}

static public function rateCeil($rate, $decimals)
{

    $div = "1" . str_repeat("0", $decimals);

    if ($rate > 0) {
        return ceil($rate * $div) / $div;
    }

    $return = ceil(abs($rate) * $div) / $div;

    return -($return);

}

Positiv

Rate: 0,00302471

Etage: 0,00302400

Decke: 0,00302500

Negativ 

Rate: -0,00302471

Etage: -0,00302400

Decke: -0,00302500

0
Jon C.

Alle Lösungen, die number_format verwenden, sind falsch, da number_format eine Rundung durchführt.

Die folgende Funktion sollte für alle Zahlen funktionieren. Sie können das Dezimaltrennzeichen für die Länder angeben, in denen ',' verwendet wird.

function truncate_decimal($number, $truncate_decimal_length = 2, $decimal_character = '.', $thousands_character = '') {

$number = explode($decimal_character, $number);
$number[1] = substr($number[1], 0, $truncate_decimal_length);
$number_truncated = implode($decimal_character, $number);
return number_format($number_truncated, $truncate_decimal_length, $decimal_character, $thousands_character);

}
0
leexonline

Eine einfache zu befolgende Funktion wäre "Wenn mehr als 0 Etage, sonst" "mit einem Multiplikator, um ihn vorübergehend über den Dezimalpunkt zu heben:

function trim_num($num_in, $dec_places = 2) {
    $multiplier = pow(10, $dec_places); // 10, 100, 1000, etc
    if ($num_in > 0) {
        $num_out = floor($num_in * $multiplier) / $multiplier;
    } else {
        $num_out = ceil($num_in * $multiplier) / $multiplier;
    }
    return $num_out;
}
0
David Bell

Das Folgende ist (was ich glaube - bitte korrigieren Sie mich wenn nicht) eine robuste mathematische * - Lösung, die hauptsächlich auf den Informationen einiger anderer Antworter basiert und eine kleine Menge von mir

(* Was nicht bedeutet, dass irgendetwas mit Liphtiers regexbasierter Antwort falsch ist - nur dass ich Puristen sehen kann, die Regex für ein wohl mathematisches Problem vermeiden wollen.)

  • sprintf(), number_format() (und natürlich round()) führen alle eine Rundung durch und sind daher nicht für die in der Frage angeforderte Rundung geeignet (zumindest nicht für sich alleine).
  • Anstelle einer Out-of-the-Box-Funktion war die scheinbar eleganteste Lösung Sujit Agarwals Antwort
  • Aber aufgrund der Art und Weise, wie Floats gespeichert werden, müssen wir ein Epsilon verwenden - wie in Antwort von David Constantine (wo er auch die vorherige Lösung allgemeiner macht, indem er pow() verwendet, um den richtigen Faktor basierend auf einer festgelegten Genauigkeit zu erhalten ).
  • Wie in der Antwort von cale_b ausgeführt, kann jedoch die Verwendung von floor() (oder vermutlich ceil()) unbeabsichtigte Ergebnisse für Negative ohne abs() ergeben.
  • Und den Wert, den ich hinzufügen möchte, ist:
    • Wenn Sie eine Division auf abs() verwenden, um einen Negationsfaktor zu erhalten, müssen wir den Sonderfall berücksichtigen, wenn die Eingabe 0 ist.
    • Wir sollten das Epsilon dynamisch erstellen; Ein statisches hartcodiertes Epsilon kann je nach erforderlicher Genauigkeit zu klein oder zu groß sein. Ich habe dieses Problem in den anderen Antworten nicht angesprochen.

Der Code, den ich verwende, lautet:

public static function truncate_decimal($number, $leavePlaces = 2)
{
    if ($number == 0) return 0;
    $negate = $number / abs($number);
    $shiftFactor = pow(10, $leavePlaces);
    $epsilon = pow(10, -1 * $leavePlaces);
    return floor(abs($number) * $shiftFactor + $epsilon) / $shiftFactor * $negate;
}
0
Sepster
$num = 118.74999669307;
$cut = substr($num, 0, ((strpos($num, '.')+1)+2));
// Cut the string from first character to a length of 2 past the decimal.
// substr(cut what, start, ( (find position of decimal)+decimal itself)+spaces after decimal) )
echo $cut; 
0
Sujjad Ali