Форматировать число до N значащих цифр в PHP

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

1        => 1
11       => 11
111      => 110
119      => 120
0.11     => 0.11
0.00011  => 0.00011
0.000111 => 0.00011

Таким образом, произвольная точность остается неизменной

Я ожидаю, что есть какая-то хорошая функция для него уже встроена, но пока не смог найти ни одной

Мне указали на Как округлить до ближайшего значащего числа в php, которое близко, но не работает для N значащих цифр, и я не уверен, что он делает с числами 0.000XXX

3 ответа

Решение

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

Это прекрасно работает для простого округления:

function sigFig($value, $digits)
{
    if ($value == 0) {
        $decimalPlaces = $digits - 1;
    } elseif ($value < 0) {
        $decimalPlaces = $digits - floor(log10($value * -1)) - 1;
    } else {
        $decimalPlaces = $digits - floor(log10($value)) - 1;
    }

    $answer = round($value, $decimalPlaces);
    return $answer;
}

Это даст следующее:
0,0001234567 возвращает 0,0001235
123456,7 возвращает 123500

Однако значение, например от 10 до 4 значимых цифр, следует строго представлять как 10,00, чтобы обозначить точность, с которой это значение известно.

Если это желаемый результат, вы можете использовать следующее:

function sigFig($value, $digits)
{
    if ($value == 0) {
        $decimalPlaces = $digits - 1;
    } elseif ($value < 0) {
        $decimalPlaces = $digits - floor(log10($value * -1)) - 1;
    } else {
        $decimalPlaces = $digits - floor(log10($value)) - 1;
    }

    $answer = ($decimalPlaces > 0) ?
        number_format($value, $decimalPlaces) : round($value, $decimalPlaces);
    return $answer;
}

Теперь 1 отображается как 1.000

С небольшой модификацией возможного дубликата ответ Тодда Чаффи:

public static function roundRate($rate, $digits)
{
    $mod = pow(10, intval(round(log10($rate))));
    $mod = $mod / pow(10, $digits);
    $answer = ((int)($rate / $mod)) * $mod;
    return $answer;
}

Чтобы sigFig(0.9995, 3) выводил 1.00, используйте

if(floor(log10 ($ value))!== floor(log10(round ($ value, $decimalPlaces)))) {$decimalPlaces--;}

Указанная строка кода должна быть размещена перед объявлением $ answer.

Если input $value отрицательный, установите флаг и удалите знак в начале функции, например:

if ($ value <0) {$flag = 1;} $ value = ltrim ($ value, "-");

Затем прямо перед возвратом $ answer определите, установлен ли флаг, и, если да, восстановите отрицательный знак, например:

if (isset ($ flag)) {$answer = "-". $ answer;}

Наконец, для значений результата с неоднозначным количеством значащих цифр (например, 1000, 12000,...), выразите результат в экспоненциальном представлении в желаемом количестве значащих цифр с помощью sprintf или printf.

Другие вопросы по тегам