как создать "красивые" номера? - PullRequest
9 голосов
/ 18 февраля 2011

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

то есть у вас естьинтервал от

130'777.12 - 542'441.17.

Но для пользователя вы хотите отобразить что-то более ... скажем, удобное для пользователя, например:

130'000 - 550'000.

как вы можете сделать это для нескольких измерений?другой пример:

23.07 - 103.50 до 20 - 150

Вы понимаете, что я имею в виду?

Я также должен дать несколько критериев:

  • интервал min и max должен включать заданные пределы.
  • "округление" должно быть в гранулярности, которая отражает расстояние между min и max (значение во втором примере 20 - 200 будетслишком грубо)

очень большая честь, которую вы заработаете, если знаете встроенную функцию php, которая может сделать это: -)

* обновление - 2011-02-21 *

Мне нравится ответ от @Ivan, и я его принял.Вот мое решение до сих пор:

возможно, вы можете сделать это лучше.Я открыт для любых предложений; -).

/**
 * formats a given float number to a well readable number for human beings
 * @author helle + ivan + greg
 * @param float $number 
 * @param boolean $min regulates wheter its the min or max of an interval
 * @return integer
 */
function pretty_number($number, $min){
    $orig = $number;
    $digit_count = floor(log($number,10))+1; //capture count of digits in number (ignoring decimals)
    switch($digit_count){
        case 0: $number = 0; break;
        case 1:
        case 2: $number = round($number/10) * 10; break;
        default: $number = round($number, (-1*($digit_count -2 )) ); break;
    }

    //be sure to include the interval borders
    if($min == true && $number > $orig){
        return pretty_number($orig - pow(10, $digit_count-2)/2, true);
    }

    if($min == false && $number < $orig){
        return pretty_number($orig + pow(10, $digit_count-2)/2, false);
    }

    return $number;

}

Ответы [ 5 ]

5 голосов
/ 18 февраля 2011

Я бы использовал Log10, чтобы определить, насколько «длинным» является число, а затем округлить его вверх или вниз. Вот быстрый и грязный пример.

echo prettyFloor(23.07);//20
echo " - ";
echo prettyCeil(103.50);//110

echo prettyFloor(130777.12);//130000
echo " - ";
echo prettyCeil(542441.17);//550000

function prettyFloor($n)
{
  $l = floor(log(abs($n),10))-1; // $l = how many digits we will have to nullify :)
  if ($l<=0)
    $l++;

  if ($l>0)
    $n=$n/(pow(10,$l)); //moving decimal point $l positions to the left eg(if $l=2 1234 => 12.34 )
  $n=floor($n);
  if ($l>0)
    $n=$n*(pow(10,$l)); //moving decimal point $l positions to the right eg(if $l=2 12.3 => 1230 )
  return $n;
}

function prettyCeil($n)
{
  $l = floor(log(abs($n),10))-1;
  if ($l<=0)
    $l++;
  if ($l>0)
    $n=$n/(pow(10,$l));
  $n=ceil($n);
  if ($l>0)
    $n=$n*(pow(10,$l));
  return $n;
}

К сожалению, этот пример не преобразует 130 в 150. Поскольку и 130, и 150 имеют одинаковую точность. Даже для нас люди выглядят немного «круглее». Для достижения такого результата я бы рекомендовал использовать десятичную систему вместо десятичной.

4 голосов
/ 18 февраля 2011

Вы можете использовать функцию php round, которая принимает параметр для определения точности.

<?php
echo round(3.4);         // 3
echo round(3.5);         // 4
echo round(3.6);         // 4
echo round(3.6, 0);      // 4
echo round(1.95583, 2);  // 1.96
echo round(1241757, -3); // 1242000
echo round(5.045, 2);    // 5.05
echo round(5.055, 2);    // 5.06
?>
1 голос
/ 18 февраля 2011

Функция number_format() обрабатывает «предварительное обогащение» чисел произвольными тысячами / десятичными символами и десятичными разрядами, но вам придется разбивать диапазоны / строки на отдельные числа, так как number_formation работает только с однимчисло за раз.

Часть округления также должна обрабатываться отдельно.

0 голосов
/ 14 мая 2019

Это на самом деле особый случай, который можно решить с помощью следующей функции:

function roundto($val, $toceil=false) { 
    $precision=2; // try 1, 2, 5, 10 
    $pow = floor(log($val, 10)); 
    $mult = pow(10, $pow);
    $a = $val/$mult*$precision; 
    if (!$toceil) $a-=0.5; else $a+=0.5; 
    return round($a)/$precision*$mult; 
}

$v0=130777.12; $v1=542441.17; 
echo number_format(roundto($v0, false), 0, '.', "'").' - '
    .number_format(roundto($v1, true), 0, '.', "'").'<br/>';

$v0=23.07; $v1=103.50; 
echo number_format(roundto($v0, false), 0, '.', "'").' - '
    .number_format(roundto($v1, true), 0, '.', "'").'<br/>';

Выводит именно это:

100'000 - 550'000
20 - 150

Для любого другого случая форматирования чиселбыло бы интересно взглянуть на мой недавно опубликованный PHP-класс " php-beautiful-numbers ", который я использую почти во всех проектах для отображения времени выполнения ("98,4 мкс" [= 9.8437291615846E-5]) или цифры в бегущем тексте (например, «вы забронировали два рейса». [= 2]).

https://github.com/SirDagen/php-beautiful-numbers

0 голосов
/ 18 февраля 2011

Я не видел готового алгоритма или функции для этого.Но это должно быть просто, основано на функции замены строк (str_replace, preg_replace), number_format и round.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...