Come arrotondare alla cifra significativa più vicino in php
-
27-10-2019 - |
Domanda
C'è un modo chiazza di petrolio verso il basso intorno alla cifra significativa più vicino in php?
0->0
9->9
10->10
17->10
77->70
114->100
745->700
1200->1000
Soluzione
$numbers = array(1, 9, 14, 53, 112, 725, 1001, 1200);
foreach($numbers as $number) {
printf('%d => %d'
, $number
, $number - $number % pow(10, floor(log10($number)))
);
echo "\n";
}
Purtroppo questo non riesce terribilmente quando $ numero è 0, ma lo fa produrre il risultato atteso per gli interi positivi. Ed è una soluzione di matematica solo.
Altri suggerimenti
Ecco una soluzione di matematica pura. Questa è anche una soluzione più flessibile, se avete sempre voluto fino rotonda o verso il basso, e non solo verso il basso. E funziona su 0:)
if($num === 0) return 0;
$digits = (int)(log10($num));
$num = (pow(10, $digits)) * floor($num/(pow(10, $digits)));
Si potrebbe sostituire floor
con round
o ceil
. In realtà, se si voleva intorno al più vicino, si potrebbe semplificare la terza linea ancora di più.
$num = round($num, -$digits);
Se si desidera avere una soluzione Mathy, provate questo:
function floorToFirst($int) {
if (0 === $int) return 0;
$nearest = pow(10, floor(log($int, 10)));
return floor($int / $nearest) * $nearest;
}
Qualcosa di simile a questo:
$str = (string)$value;
echo (int)($str[0] . str_repeat('0', strlen($str) - 1));
E 'totalmente non-Mathy, ma vorrei solo fare questa lunghezza utilizzando pungere ... probabilmente c'è un modo più agevole da gestire, ma si potrebbe compire con
function significant($number){
$digits = count($number);
if($digits >= 2){
$newNumber = substr($number,0,1);
$digits--;
for($i = 0; $i < $digits; $i++){
$newNumber = $newNumber . "0";
}
}
return $newNumber;
}
Una matematica basato alternativa:
$mod = pow(10, intval(round(log10($value) - 0.5)));
$answer = ((int)($value / $mod)) * $mod;
So che questo è un vecchio thread, ma ho letto che quando alla ricerca di ispirazione su come risolvere questo problema. Ecco quello che mi si avvicinò con:
class Math
{
public static function round($number, $numberOfSigFigs = 1)
{
// If the number is 0 return 0
if ($number == 0) {
return 0;
}
// Deal with negative numbers
if ($number < 0) {
$number = -$number;
return -Math::sigFigRound($number, $numberOfSigFigs);
}
return Math::sigFigRound($number, $numberOfSigFigs);
}
private static function sigFigRound($number, $numberOfSigFigs)
{
// Log the number passed
$log = log10($number);
// Round $log down to determine the integer part of the log
$logIntegerPart = floor($log);
// Subtract the integer part from the log itself to determine the fractional part of the log
$logFractionalPart = $log - $logIntegerPart;
// Calculate the value of 10 raised to the power of $logFractionalPart
$value = pow(10, $logFractionalPart);
// Round $value to specified number of significant figures
$value = round($value, $numberOfSigFigs - 1);
// Return the correct value
return $value * pow(10, $logIntegerPart);
}
}
Mentre le funzioni qui hanno lavorato, avevo bisogno di cifre significative per numeri molto piccoli (confronto basso valore criptovaluta a Bitcoin).
La risposta a a N cifre significative in PHP ha lavorato, in qualche modo, anche se molto piccoli numeri vengono visualizzati da PHP in notazione scientifica, che li rende difficile per alcune persone a leggere.
Ho provato ad utilizzare number_format, però che necessita di un numero specifico di cifre dopo il decimale, che ha rotto la parte 'significativa' del numero (se viene inserito un numero fisso) e talvolta tornati 0 (per i numeri più piccoli del numero impostato ).
La soluzione era quella di modificare la funzione di identificare realmente piccoli numeri e quindi utilizzare number_format su di loro - di prendere il numero di cifre notazione scientifica come il numero di cifre per number_format:
function roundRate($rate, $digits)
{
$mod = pow(10, intval(round(log10($rate))));
$mod = $mod / pow(10, $digits);
$answer = ((int)($rate / $mod)) * $mod;
$small = strstr($answer,"-");
if($small)
{
$answer = number_format($answer,str_replace("-","",$small));
}
return $answer;
}
Questa funzione mantiene le cifre significative e presenta i numeri in formato di facile lettura per tutti. (Lo so, non è la migliore per le persone scientifici e nemmeno la lunghezza più costantemente 'abbastanza' guardando i numeri, ma nel complesso è la soluzione migliore per quello che ci serviva.)