Existe-t-il un moyen simple de déterminer le nombre de décimales dans a(n) entier/double valeur en PHP? (c’est-à-dire sans utiliser explode
)
$str = "1.23444";
print strlen(substr(strrchr($str, "."), 1));
function numberOfDecimals($value)
{
if ((int)$value == $value)
{
return 0;
}
else if (! is_numeric($value))
{
// throw new Exception('numberOfDecimals: ' . $value . ' is not a number!');
return false;
}
return strlen($value) - strrpos($value, '.') - 1;
}
/* test and proof */
function test($value)
{
printf("Testing [%s] : %d decimals\n", $value, numberOfDecimals($value));
}
foreach(array(1, 1.1, 1.22, 123.456, 0, 1.0, '1.0', 'not a number') as $value)
{
test($value);
}
Les sorties:
Testing [1] : 0 decimals
Testing [1.1] : 1 decimals
Testing [1.22] : 2 decimals
Testing [123.456] : 3 decimals
Testing [0] : 0 decimals
Testing [1] : 0 decimals
Testing [1.0] : 0 decimals
Testing [not a number] : 0 decimals
Vous pouvez essayer de le convertir en int, de le soustraire de votre nombre et de compter ensuite ce qui reste.
J'ai utilisé ce qui suit pour déterminer si une valeur renvoyée a des décimales (valeurs décimales réelles, pas seulement formatées pour afficher des décimales telles que 100,00):
if($mynum - floor($mynum)>0) {has decimals;} else {no decimals;}
<?php
test(0);
test(1);
test(1.234567890);
test(-123.14);
test(1234567890);
test(12345.67890);
function test($f) {
echo "f = $f\n";
echo "i = ".getIntCount($f)."\n";
echo "d = ".getDecCount($f)."\n";
echo "\n";
}
function getIntCount($f) {
if ($f === 0) {
return 1;
} elseif ($f < 0) {
return getIntCount(-$f);
} else {
return floor(log10(floor($f))) + 1;
}
}
function getDecCount($f) {
$num = 0;
while (true) {
if ((string)$f === (string)round($f)) {
break;
}
if (is_infinite($f)) {
break;
}
$f *= 10;
$num++;
}
return $num;
}
Les sorties:
f = 0
i = 1
d = 0
f = 1
i = 1
d = 0
f = 1.23456789
i = 1
d = 8
f = -123.14
i = 3
d = 2
f = 1234567890
i = 10
d = 0
f = 12345.6789
i = 5
d = 4
J'avais besoin d'une solution fonctionnant avec différents formats de nombres et proposant les algorithmes suivants:
// Count the number of decimal places
$current = $value - floor($value);
for ($decimals = 0; ceil($current); $decimals++) {
$current = ($value * pow(10, $decimals + 1)) - floor($value * pow(10, $decimals + 1));
}
// Count the total number of digits (includes decimal places)
$current = floor($value);
for ($digits = $decimals; $current; $digits++) {
$current = floor($current / 10);
}
Résultats:
input: 1
decimals: 0
digits: 1
input: 100
decimals: 0
digits: 3
input: 0.04
decimals: 2
digits: 2
input: 10.004
decimals: 3
digits: 5
input: 10.0000001
decimals: 7
digits: 9
input: 1.2000000992884E-10
decimals: 24
digits: 24
input: 1.2000000992884e6
decimals: 7
digits: 14
Quelque chose comme:
<?php
$floatNum = "120.340304";
$length = strlen($floatNum);
$pos = strpos($floatNum, "."); // zero-based counting.
$num_of_dec_places = ($length - $pos) - 1; // -1 to compensate for the zero-based count in strpos()
?>
C'est procédural, kludgy et je ne conseillerais pas de l'utiliser en code de production. Mais cela devrait vous aider à démarrer.
Les entiers n'ayant pas de chiffres décimaux, la réponse est toujours zéro.
Les nombres doubles ou flottants sont approximatifs. Donc, ils n'ont pas un nombre défini de chiffres décimaux.
Un petit exemple:
$number = 12.00000000012;
$frac = $number - (int)$number;
var_dump($number);
var_dump($frac);
Sortie:
float(12.00000000012)
float(1.2000000992884E-10)
Vous pouvez voir deux problèmes ici, le deuxième nombre utilise la représentation scientifique et ce n'est pas exactement 1.2E-10.
Pour une chaîne contenant un entier/float, vous pouvez rechercher le point décimal:
$string = '12.00000000012';
$delimiterPosition = strrpos($string, '.');
var_dump(
$delimiterPosition === FALSE ? 0 : strlen($string) - 1 - $delimiterPosition
);
Sortie:
int(11)
Si vous voulez de la lisibilité au profit d'autres développeurs, respectez les paramètres régionaux, utilisez:
function countDecimalPlacesUsingStrrpos($stringValue){
$locale_info = localeconv();
$pos = strrpos($stringValue, $locale_info['decimal_point']);
if ($pos !== false) {
return strlen($stringValue) - ($pos + 1);
}
return 0;
}
voir localeconv
Que dis-tu de ça?:
$iDecimals = strlen($sFull%1);
Voici une fonction qui prend en compte les zéros de fin:
function get_precision($value) {
if (!is_numeric($value)) { return false; }
$decimal = $value - floor($value); //get the decimal portion of the number
if ($decimal == 0) { return 0; } //if it's a whole number
$precision = strlen($decimal) - 2; //-2 to account for "0."
return $precision;
}
$num = "12.1234567";
print strlen(preg_replace("/.*\./", "", $num)); // 7
Le motif ". * \. " signifie tous les caractères précédant le point décimal avec son.
Dans ce cas, c'est une chaîne avec trois caractères: " 12. ".
preg_replace function convertit ces caractères en une chaîne vide (second paramètre).
Dans ce cas, nous obtenons cette chaîne: " 1234567 ".
strlen function compte le nombre de caractères dans la chaîne ci-dessus.
$decnumber = strlen(strstr($yourstr,'.'))-1
J'ai d'abord trouvé l'emplacement de la décimale à l'aide de la fonction strpos
et incrémenté la valeur de la position strpos
de 1 pour ignorer la décimale.
Deuxièmement, j'ai soustrait toute la longueur de la chaîne de la valeur du point1.
Troisièmement, j'ai utilisé la fonction substr
pour obtenir tous les chiffres après la virgule.
Quatrièmement, j'ai utilisé la fonction strlen
pour obtenir la longueur de la chaîne après la décimale.
C'est le code qui effectue les étapes décrites ci-dessus:
<?php
$str="98.6754332";
echo $str;
echo "<br/>";
echo substr( $str, -(strlen($str)-(strpos($str, '.')+1)) );
echo "<br/>";
echo strlen( substr( $str, -(strlen($str)-(strpos($str, '.')+1))) );
?>
Vous devriez toujours faire attention à différents endroits. Les paramètres régionaux européens utilisent une virgule pour séparer les milliers, de sorte que la réponse acceptée ne fonctionne pas. Voir ci-dessous pour une solution révisée:
function countDecimalsUsingStrchr($stringValue){
$locale_info = localeconv();
return strlen(substr(strrchr($stringValue, $locale_info['decimal_point']), 1));
}
voir localeconv
Cela fonctionnera pour tous les nombres, même en notation scientifique, avec une précision allant jusqu'à 100 décimales.
$float = 0.0000005;
$working = number_format($float,100);
$working = rtrim($working,"0");
$working = explode(".",$working);
$working = $working[1];
$decmial_places = strlen($working);
Résultat:
7
Longue mais fonctionne sans condition complexe.