如何在PHP中给正数加上加号前缀

30

我需要设计一个函数,使负数返回其本身,但是如果一个数字已经没有加号,则在数字前面添加“+”标记。

例如:

Input     Output
----------------
+1         +1
1          +1
-1         -1

它将仅获取数字输入。

function formatNum($num)
{
# something here..perhaps a regex?
}

这个函数将在echo/print中被调用多次,所以速度越快越好。


1
“+ve”和“-ve”是什么意思? - Joachim Sauer
Joachim,很抱歉,我不知道那些是非标准的短表示形式。 - user318466
应该将 0 视为正数吗? - Wolf
7个回答

81

你可以使用正则表达式:

function formatNum($num){
    return preg_replace('/^(\d+)$/',"+$1",$num);
}

但是我建议不要使用正则表达式来处理这么简单的事情。最好使用sprintf函数,如下所示:

function formatNum($num){
    return sprintf("%+d",$num);
}

来自PHP手册中的sprintf

一个可选的符号说明符,可以强制在数字上使用符号(-或+)。默认情况下,仅当数字为负数时才使用-号。 此说明符可以强制使正数附带+符号,并且是在PHP 4.3.0中添加的。


10
+1 用于 sprintf (我想知道为什么一开始没有人建议使用它 ;),但你比我快 :-D) - Felix Kling
unicornaddict:为什么不使用正则表达式?我听说它们很强大。它们不是吗? - user318466
3
它们很强大,但往往比纯字符串函数慢得明显。 - pinkgothic
2
运行良好。我选择了sprintf而不是正则表达式,就像你们专家建议的那样。 - user318466
7
对于像问题所询问的格式化字符串打印,应该首先考虑使用sprintf,这个解答获得了+1的评价。但在一个好的回答前面(似乎是随机地?)加上正则表达式的解决方案,则获得了-1的评价。 - salathe
显示剩余3条评论

8
function formatNum($num) {
   return ((float) $num>0)?'+'.$num:$num;
}

3
如果我输入+1,它会返回++1 :((注:原文中的“pass”可能是指某个程序中的语句,但缺少上下文无法确定具体含义,因此本翻译将其翻译为“输入”) - user318466
2
如果你传递了 +1,它会返回 +1。如果你将 '+1' 作为字符串传递,则它会返回 ++1。不过,我更喜欢 UnicornAddict 的 sprintf 方法。 - Dal Hundal
由于 OP 告诉我们 sprintf 做了正确的事情,你可能需要重新考虑你的答案。 - Wolf
我编辑了这篇文章,将其转换为数字以避免Dan Hundal提到的++1错误。 - Joe Love

3
function formatNum($num) {
  $num = (int) $num; // or (float) if you'd rather
  return (($num >= 0) ? '+' : '') . $num; // implicit cast back to string
}

@Wolf 虽然我已经十年没有看过这个问题了,但是简要回顾一下,我相当确定这段代码的作用(>= 0 测试正数,并在其为真时添加 +)。你能详细说明你在哪里看到了错误的比较运算符吗? - pinkgothic
在问题描述中再次审查它(该问题使用positive和您一样的方式),如果零值应该像sprintf一样处理,那么您的函数是正确的。不幸的是,OP选择了一个模糊的示例集。因此,我们现在有两个答案,不同的结果都是正确的。在问题中要求格式化非负数或添加+0会更好,但这显然不是您的错。由于您正在正确处理现有的符号,因此应该优先选择您的方法而不是Dan的方法。 - Wolf

2

试试这个:

$fmt = new NumberFormatter('es_ES', NumberFormatter::DECIMAL);
$fmt->setTextAttribute(NumberFormatter::POSITIVE_PREFIX, '+');
$result = $fmt->format(10000);

结果将是:+10.000

NumberFormatter::POSITIVE_SUFFIX正好起作用,您将收到10.000+


2
简单的解决方案是在printf()函数中使用格式说明符。
例如,
$num1=2;
$num2=-2;
printf("%+d",$num1);
echo '<br>';
printf("%+d",$num2);

输出结果

+2
-2

在你的情况下
 function formatNum($num){
    return printf("%+d",$num);
 }

使用sprintf("%+d",$num);代替0输出+02 - Tim Visée

0

@unicornaddict 提供的 sprintf 解决方案非常好,可能是最优雅的方法。我只是想提供另一种选择。不确定它们在速度上如何比较。

// Non float safe version
function formatNum($num) {
    return (abs($num) == $num ? '+' : '') . intval($num);
}

// Float safe version
function formatNum($num) {
    return 
        (abs($num) == $num ? '+' : '') 
        . (intval($num) == $num ? intval($num) : floatval($num));
}

// Float safe version, alternative
function formatNum($num) {
    return 
        (abs($num) == $num ? '+' : '') 
        // Add '1' to $num to implicitly cast it to a number
        . (is_float($num + 1) ? floatval($num) : intval($num));
} 

与其使用intval(),不如只使用return (((string)abs($num)) === $num) ? '+' . $num : $num; - 尽管这可能仅适用于整数?[我有点偏执,天哪。] - pinkgothic
问题不在于比较部分,而在于返回部分。我已编辑了我的示例,但正如您所提到的那样,它只适用于整数。修改为支持浮点数也很简单,但这可能只会证明为什么 sprintf 是更好的选择。 - nikc.org
同意关于sprintf的观点!不过我不确定将其修改为适用于浮点数是否容易,因为字符串可能无法表示为可以存储为浮点数的浮点数,然后从浮点数转换回字符串会产生一个本来不存在的差异? - pinkgothic
PHP的好处(有时候也可能不是)在于你不需要进行类型转换。数据会在上下文中自动进行类型转换。但是对于浮点数进行修改非常简单,我就忍不住进行了修改;-) - nikc.org
数据在上下文中自动类型转换。是的,但它确实被转换了。我的问题是abs("0.000000000000001")是否与"0.000000000000001"相同(==)。我想这归结为一个问题:我不信任浮点数。 :)) 我应该只是玩一下这个,看看结果。(请注意,除此之外,“is_float”对于字符串始终将返回“false”。) - pinkgothic
浮点数不可信,你怀疑是正确的。我可能错了,但据我所知,关于浮点数,不应该(永远!)信任/使用的是相等比较。小于/大于比较应该是可靠的。此外,我可能在这样做时错了,我相信内部将能够正确处理浮点数。(sprintf 的又一个优点。)但对于你所举的精度,测试你的需求证明了它的重要性。特别是如果依赖于 int 强制转换。 (你指出 is_float 的不合逻辑(关于 PHP 的非严格类型)缺陷是正确的,请参见修订版。) - nikc.org

0

好的,这可能有点老旧且无用,但我认为仍然有一些空间可以稍作添加。如果您已经有了“数字”:

if($num>=0) $num='+'.(0+$num);

或者,如果您确定它是一个数字:

if($num>=0) $num='+'.$num;
  • 对于负数不起作用,如果是正数则转换为字符串。

  • 添加0会将其转换为数字(如果它不是数字),并且不会更改数字类型,例如强制转换为(float)或(int)。如果您确定它是数字,则此方法无用,请使用第二个版本。

  • 这可能是最快的方法。

  • 缺点是一半结果为字符串,一半为数字(sprintf将使它们全部成为字符串)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接