如何创建“漂亮”的数字?

时间:2011-02-18 16:14:59

标签: php algorithm numbers usability

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

即。你有一个间隔

130'777.12 - 542'441.17

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

130'000 - 550'000

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

23.07 - 103.5020 - 150

你了解我的意思吗?

我也应该给出一些标准:

  • 间隔min和max应该 包括给定的限制。
  • “舍入”应该在a 粒度反映了 最小和最大之间的距离(意思是 在我们的第二个例子中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 个答案:

答案 0 :(得分: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;
}

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

答案 1 :(得分:4)

你可以使用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
?>

答案 2 :(得分:1)

number_format()函数使用任意数千/十进制字符和小数位来处理“美化”数字,但是您必须将范围/字符串拆分为单个数字,因为number_formation一次只能处理一个数字

圆角部分也必须单独处理。

答案 3 :(得分:0)

我还没有看到准备好的算法或功能。但它应该很简单,基于字符串替换(str_replacepreg_replace),number_formatround函数。

答案 4 :(得分:0)

这实际上是一种特殊情况,可以使用以下功能解决:

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µµs” [= 9.8437291615846E-5])或连续文字中的数字(例如“您预订了两个航班。” [= 2])。

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