如何创建"漂亮"的数字?

hel*_*lle 9 php algorithm usability numbers

我的问题是:是否有一个很好的(通用)算法来创建数字,这些数字与用户理解的数字相匹配(从随机寻找用户的数字)数字.

即你有一个间隔

130'777.12 - 542'441.17.

但是对于用户来说,你想要展示更多东西...说用户友好,比如:

130'000 - 550'000.

你怎么能在几个方面做到这一点?另一个例子是:

23.07 - 103.5020 - 150

你明白我的意思吗?

我也应该给出一些标准:

  • 间隔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;

}
Run Code Online (Sandbox Code Playgroud)

Iva*_*van 5

我会使用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;
}
Run Code Online (Sandbox Code Playgroud)

遗憾的是,这个例子不会将130转换为150.因为130和150具有相同的精度.即使你为我们,人类150看起来有点"圆".为了达到这样的结果,我建议使用quinary系统而不是decimal.

  • 的确,你可以.只是放($ n, - (floor(log($ n,10)) - 1)).但是在这种情况下,您无法确定初始范围是舍入范围的子集,例如99-201将舍入为100-200 (2认同)