web-dev-qa-db-fra.com

Supprimer les chiffres après deux décimales, sans arrondir la valeur

j'ai valeur en variable php comme ça

$var='2.500000550';
echo $var

ce que je veux, c'est supprimer tous les points décimaux après 2 chiffres.

comme maintenant la valeur de la variable sera

$var='2.50';
echo $var

gardez à l'esprit que cette valeur provient de mysql databse

mais quand j’utilise round php function j’ai fait le tour mais je n’ai pas besoin de tour, j’ai juste besoin de supprimer tous les chiffres après 2 décimales simples.

je suis fatigué, flot() et beaucoup d'autres options sans succès.

Merci

38
air

TL; DR:

La fonction native PHP bcdiv semble faire exactement ce qui est requis, et correctement.

Pour simplement "tronquer" un nombre, bcdiv($var, 1, 2); où 2 est le nombre de décimales à conserver (et 1 est le dénomination - diviser le nombre par 1 vous permet simplement de tronquer le nombre d'origine aux décimales souhaitées).

Réponse complète (pour l'historique)

Cela s'avère être plus insaisissable qu'on pourrait le penser.

Après que cette réponse ait été (à tort) assez votée, il m'est apparu que même le sprintf allait s'arrêter.

Plutôt que de supprimer cette réponse, je la transforme en une explication/discussion plus robuste de chaque solution proposée.

number_format - Incorrect. (tours)
Essayez d'utiliser le format nombre :

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

Si vous voulez que ce soit un nombre, tapez simplement le transtypage en float:

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

Note: comme cela a été souligné dans les commentaires, cela fait en fait arrondi le nombre.

sprintf - incorrect. (sprintf aussi rond)
S'il n'est pas important d'arrondir le nombre, utilisez la réponse sprintf :

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

étage - pas tout à fait! (le sol arrondit les nombres négatifs) 

floor , avec quelques maths, sera presque près de faire ce que vous voulez:

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

Où 100 représente la précision que vous souhaitez. Si vous le vouliez à trois chiffres, alors:

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

Cependant, cela pose un problème avec les nombres négatifs. Les nombres négatifs sont toujours arrondis plutôt que tronqués:

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

"Ancien" Réponse correcte: fonction utilisant le sol

Une solution totalement robuste nécessite donc une fonction:

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

Résultats de la fonction ci-dessus:

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

Nouvelle réponse correcte

Utilisez la fonction native 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;

Cela devrait faire votre tâche ...

9
Sujit Agarwal

Vous demandez une fonction qui retourne "2.50" et non pas 2.5, donc vous ne parlez pas d'arithmétique ici mais de manipulation de chaîne . Alors preg_replace est votre ami:

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

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

Si vous voulez le faire en arithmétique, utilisez simplement: 

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

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

essayez avec number_format :

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

number_format arrondit le nombre 

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

J'ai utilisé preg_replace pour vraiment couper la ficelle

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

utilisez sprintf

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

Utilisez la fonction native PHP bcdiv

Exemple:

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

Pour votre cas:

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

quelqu'un posté ici à propos de 

plancher (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

donc, à l'état brut, ne l'utilisez pas ... Mais si vous ajoutez un peu d'epsilon ...

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

Ça marche!

2
David Constantine

étage - pas tout à fait! (le sol arrondit les nombres négatifs) 

Une solution possible de 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);

}

Positif

Taux: 0,00302471

Étage: 0.00302400

Ceil: 0.00302500

Négatif 

Taux: -0,00302471

Etage: -0.00302400

Ceil: -0.00302500

0
Jon C.

Toutes les solutions qui utilisent number_format sont incorrectes car number_format effectue l'arrondi.

La fonction ci-dessous devrait fonctionner sur tous les nombres, vous pouvez spécifier le séparateur décimal pour les pays qui utilisent ','.

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

Une fonction simple à suivre serait "Si supérieur à 0 plancher, sinon ceil", en utilisant un multiplicateur pour le lever temporairement au-dessus du point décimal tout en le faisant:

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

Ce qui suit est (ce que je pense - corrigez-moi si nécessaire) une solution robuste mathématique *, basée principalement sur les informations de plusieurs autres répondants, et une petite quantité de moi

(* Cela ne veut pas dire qu'il y a quelque chose qui ne va pas avec la réponse de Liphtier basée sur les expressions rationnelles - juste que je vois des puristes vouloir éviter les expressions régulières pour ce qui est sans doute un problème mathématique.)

  • sprintf(), number_format() (et round(), évidemment), effectuent tous une opération d'arrondi; ils ne conviennent donc pas pour la troncature sans arrondi demandée dans la question (du moins pas par eux-mêmes).
  • Au lieu d'une fonction clé en main, la solution apparemment la plus élégante était La réponse de Sujit Agarwal
  • Mais à cause de la manière dont les flottants sont stockés, nous devons utiliser un epsilon - comme indiqué dans la réponse de David Constantine (où il donne également une solution plus générale à la solution précédente en utilisant pow() pour obtenir le bon facteur en fonction d'une précision spécifiée ).
  • Mais alors, comme indiqué dans la réponse de cale_b , toute utilisation de floor() (ou vraisemblablement ceil()) peut produire des résultats inattendus pour les négatifs sans utiliser de abs().
  • Et la valeur que j'essaie d'ajouter est la suivante:
    • Si vous utilisez une division sur abs() pour obtenir un facteur de négation, vous devez tenir compte du cas particulier où l'entrée est 0.
    • Nous devrions créer dynamiquement le epsilon; Un epsilon statique codé en dur peut être trop petit ou trop grand, en fonction de la précision requise. Je n'ai pas vu cette question abordée dans les autres réponses.

Le code que j'utilise est:

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