如何创造“漂亮”数字?

发布于 2024-10-18 05:29:14 字数 1572 浏览 5 评论 0原文

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

即您的时间间隔为

130'777.12 - 542'441.17

但对于用户来说,您希望显示更多内容……比如用户友好的内容,例如:

130'000 - 550'000

如何在多个维度上做到这一点? 另一个例子是:

23.07 - 103.5020 - 150

你明白我的意思吗?

我还应该给出一些标准:

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

}

my question is: is there a good (common) algorithm to create numbers, which match well looking user understood numbers out of incomming (kind of random looking for a user) numbers.

i.e. you have an interval from

130'777.12 - 542'441.17.

But for the user you want to display something more ...say userfriendly, like:

130'000 - 550'000.

how can you do this for several dimensions?
an other example would be:

23.07 - 103.50 to 20 - 150

do you understand what i mean?

i should give some criteria as well:

  • the interval min and max should
    include the given limits.
  • the "rounding" should be in a
    granularity which reflects the
    distance between min and max (meaning
    in our second example 20 - 200
    would be too coarse)

very much honor you'll earn if you know a native php function which can do this :-)

*update - 2011-02-21 *

I like the answer from @Ivan and so accepted it. Here is my solution so far:

maybe you can do it better. i am open for any proposals ;-).

/**
 * 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;

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

狼性发作 2024-10-25 05:29:14

我会使用 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 看起来也有点“圆”。为了达到这样的结果,我建议使用五进制而不是十进制。

I would use Log10 to find how "long" the number is and then round it up or down. Here's a quick and dirty example.

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;
}

This example unfortunately will not convert 130 to 150. As both 130 and 150 have the same precision. Even thou for us, humans 150 looks a bit "rounder". In order to achieve such result I would recommend to use quinary system instead of decimal.

一人独醉 2024-10-25 05:29:14

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

You can use php's round function which takes a parameter to specify the precision.

<?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
?>
清秋悲枫 2024-10-25 05:29:14

number_format() 函数处理具有任意千位/十进制字符和小数的“美化”数字位置,但您必须将范围/字符串拆分为单独的数字,因为 number_formation 一次仅适用于一个数字。

舍入部分也必须单独处理。

The number_format() function handles "prettifying" numbers with arbitrary thousands/decimal characters and decimal places, but you'd have to split your ranges/strings into individual numbers, as number_formation only works on one number at a time.

The rounding portion would have to handled seperately as well.

无戏配角 2024-10-25 05:29:14

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

I haven't seen ready algorithm or function for that. But it should be simple, based on string replacement (str_replace, preg_replace), number_format and round functions.

浮光之海 2024-10-25 05:29:14

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

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

This actually is kind of a special case, that can be addressed with the following function:

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/>';

Outputs exactly this:

100'000 - 550'000
20 - 150

For any other case of number formatting it might be interesting to have a look at my newly published PHP class "php-beautiful-numbers", which I use in almost ever project to display run times ("98.4 µs" [= 9.8437291615846E-5]) or numbers in running text (e.g. "you booked two flights." [= 2]).

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文