Как округлить до ближайшего значимого числа в php - PullRequest
5 голосов
/ 29 апреля 2011

Есть ли какой-нибудь плавный способ округления до ближайшей значащей цифры в php?

Итак:

0->0
9->9
10->10
17->10
77->70
114->100
745->700
1200->1000

?

Ответы [ 8 ]

7 голосов
/ 29 апреля 2011
$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";
}

К сожалению, это ужасно не получается, когда $ number равно 0, но это дает ожидаемый результат для положительных целых чисел.И это математическое решение.

4 голосов
/ 29 апреля 2011

Вот чистое математическое решение.Это также более гибкое решение, если вы когда-нибудь хотели округлить вверх или вниз, а не просто вниз.И это работает на 0:)

if($num === 0) return 0;
$digits = (int)(log10($num));
$num = (pow(10, $digits)) * floor($num/(pow(10, $digits)));

Вы можете заменить floor на round или ceil.На самом деле, если вы хотите округлить до ближайшего, вы можете упростить третью строку еще больше.

$num = round($num, -$digits);
3 голосов
/ 29 апреля 2011

Если вы хотите получить математическое решение, попробуйте это:

function floorToFirst($int) {
    if (0 === $int) return 0;

    $nearest = pow(10, floor(log($int, 10)));
    return floor($int / $nearest) * $nearest;
}
1 голос
/ 19 декабря 2015

Я знаю, что это старая ветка, но я прочитал ее, когда искал вдохновение о том, как решить эту проблему. Вот что я придумал:

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); 
    }
}
1 голос
/ 29 апреля 2011

Математическая альтернатива:

$mod = pow(10, intval(round(log10($value) - 0.5))); 
$answer = ((int)($value / $mod)) * $mod;
1 голос
/ 29 апреля 2011

Это совершенно не математика, но я бы просто сделал это, используя длину жала ... возможно, есть более плавный способ справиться с этим, но вы могли бы дополнить его с помощью

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;
}
1 голос
/ 29 апреля 2011

Примерно так:

$str = (string)$value;
echo (int)($str[0] . str_repeat('0', strlen($str) - 1));
0 голосов
/ 18 февраля 2018

В то время как функции здесь работали, мне нужно было значащие цифры для очень маленьких чисел (сравнивая криптовалюту с низким значением и биткойны).

Ответ на Форматирование числа в N значащих цифр в PHP сработало, несколько, хотя очень маленькие числа отображаются PHP в научной нотации, что затрудняет их чтение некоторыми людьми.

enter image description here

Я пытался использоватьnumber_format, хотя для этого требуется определенное количество цифр после десятичной дроби, которое разбивает «значительную» часть числа (если введено заданное число) и иногда возвращает 0 (для чисел, меньших, чем заданное число).

Решение состояло в том, чтобы изменить функцию, чтобы она идентифицировала действительно маленькие числа, а затем использовать для них number_format - принимая количество цифр научных обозначений в качестве числа цифр для 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;
}

ThisФункция сохраняет значащие цифры, а также представляет цифры в удобном для чтения формате для всех.(Я знаю, что это не самое лучшее для научных людей, и даже не самые привлекательные цифры, но в целом это лучшее решение для того, что нам нужно.)

enter image description here

...