带有可变小数位的数字格式

时间:2016-05-13 07:48:57

标签: php

是否有一种内置/整洁的方式来格式化数字(就像number_format那样),但没有任何舍入上升/下降?

例如,数字1234.234的格式应为1,234.234,而另一个数字1234的格式应为1,234(即没有任何尾随.000)< / p>

6 个答案:

答案 0 :(得分:4)

您可以为此定义简单的自定义函数:

<?php
    function custom_number_format($number, $decimal = '.')
    {
        $broken_number = explode($decimal, $number);
        if (isset($broken_number[1]))
            return number_format($broken_number[0]) . $decimal . $broken_number[1];
        else
            return number_format($broken_number[0]);
    }

    $n1 = '1234.234';
    $n2 = '1234';

    echo custom_number_format($n1);
    echo '<br>';
    echo custom_number_format($n2);
?>

输出是:

1,234.234
1,234

答案 1 :(得分:1)

我真的很喜欢arhey的回答,但后来意识到它有一个重大缺陷。像2100这样的数字将转换为2,1而不是2,100

以下是我最终修改它的方法。

public function formatDecimal($number)
{
    $stringVal = strval($number); //convert number to string

    $decPosition = strpos($stringVal, ".");

    if ($decPosition !== false) //there is a decimal
    {
        $decPart = substr($stringVal, $decPosition); //grab only the decimal portion

        $result = number_format($stringVal) . rtrim($decPart, ".0");
    }
    else //no decimal to worry about
    {
        $result = number_format($stringVal);
    }

    return $result;
}

它并不像我希望的那样简洁,但在我的情况下,我将它放入一个视图帮助器(我使用的是ZF2),所以在我看来它只是一个简单的函数调用。

希望这对某人有帮助!

答案 2 :(得分:1)

基于Arhey的答案

TLDR;)

您可以使用number_format将数字格式化为固定宽度格式,然后使用rtrim两次以删除前导零和点。

rtrim(rtrim(number_format($number, 3, '.', ','), '0'), '.')

从最后一个字符开始,如果rtrim是给定的字符之一,则将其删除。在我们的示例中,我们先删除前导点,然后再删除最终的前导零。

rtrim(rtrim(number_format(1234.123, 3, '.', ','), '0'), '.')
// returns 1,234.123

rtrim(rtrim(number_format(1234.12, 3, '.', ','), '0'), '.')
// returns 1,234.12 (1,234.120, trimmed to 1234.12)

rtrim(rtrim(number_format(1234, 3, '.', ','), '0'), '.')
// returns 1,234 (1,234.000, trimmed to 1234)

rtrim(rtrim(number_format(1200, 3, '.', ','), '0'),'.')
// returns 1,200 (1,200.000, trimmed to 1200., trimmed to 1200)

形式,以及有关参数(特别是小数)的讨论

rtrim(rtrim(number_format($number, <N>, '<D>', ''), '0'), '<D>')

位置:

  • D 是小数点分隔符。为避免区域设置格式问题,请明确指定
  • N 是您可以使用的最大位数。

如果您知道所有数字都少于3个数字,请取N = 3。

如果您最多不知道多少个小数怎么办?好吧,事情变得越来越复杂。 可能值得回忆(如the PHP documentation中所述),浮点数已存储:

  • 具有 precision (精度为 )(不是小数点之前还是之后的数字,不区分大小写),而不是小数位数
  • 以及它们的 binary 形式,而不是其十进制形式,这会在达到精度限制时导致舍入错误。
  

例如,floor((0.1 + 0.7)* 10)通常返回7而不是   预期8,因为内部表示将类似于   7.9999999999999991118 ....

因此,没有普遍的良好价值,您必须根据数据的通常规模来选择它。

这说明了为什么没有内置功能的原因:PHP无法为您选择。

答案 3 :(得分:0)

让我们先从PHP中没有十进制类型开始。只有浮动。

如果你知道浮点数是如何工作的,那么你就知道通常不可能存储你认为有的精确十进制值,但这是一个近似值。那是因为你无法在二进制系统中表达大多数十进制数。

因此,如果你说:

$number = 1234.234;

然后你有一个接近这个值的浮点数。真正的价值是:

1234.23399999999992360244505107402801513671875

因此,PHP无法猜测你想如何围绕它。需要明确指定。

答案 4 :(得分:0)

rtrim(number_format(1234.234, 3),'.0');
rtrim(number_format(1234, 3),'.0');

答案 5 :(得分:0)

您可以使用功能:

<?php
function getNumberFormat($number) {
    $numberAr = explode('.', (string)$number);

    $count = 0;
    if (2 === count($numberAr)) {
        $count = strlen($numberAr[1]);
    }

    return number_format($number, $count, ',', '.');
}

$test1 = 1234.234;
$test2 = 1234;                      
echo getNumberFormat($test1); //1,234.234
echo getNumberFormat($test2); //1,234