【问题标题】:How to strip trailing zeros in PHP如何在 PHP 中去除尾随零
【发布时间】:2011-03-01 00:13:09
【问题描述】:

谁能给我一个解释(也许是一个例子)如何使用 PHP 从数字中去除尾随零。

例如:

"Lat":"37.422005000000000000000000000000","Lon":"-122.84095000000000000000000000000"

将转为:

"Lat":"37.422005","Lon":"-122.84095"

我正在尝试去除零以使其更具可读性。我尝试使用str_replace(),但这也替换了数字内的零。

【问题讨论】:

  • 老兄,加到 0, $a += 0;在此处查看详细信息:nabtron.com/kiss-code
  • @NabeelKhan 我建议将$a + 0 分配给一个新变量,而不是使用+=,这将改变$a 的类型。

标签: php string


【解决方案1】:

忘记所有的 rtrims 和正则表达式,坐标是浮点数,应该被视为浮点数,只需在变量前面加上 (float) 即可将其从字符串转换为浮点数:

$string = "37.422005000000000000000000000000";
echo (float)$string;

输出:

37.422005

您的实际结果是浮点数,但由于 HTTP 协议而作为字符串传递给您,最好将它们转回其自然形式以进行计算等。

测试用例:http://codepad.org/TVb2Xyy3

注意:关于PHP中浮点精度的注释,见:https://stackoverflow.com/a/3726761/353790

【讨论】:

  • 错误的解决方案。浮点数具有有限的精度;这可能会截断有效数字。
  • 我不认为这是一个糟糕的解决方案,我认为这是该语言的更好解决方案之一,如果 OP 需要精度,那么 OP 应该考虑使用 C、C#、Python 等确实支持有限精度。
  • 我猜如果数字是“0.0000085”,那么这些不会有用,例如,结果将类似于“8.5E-5”
  • 大声笑,老兄,只需将字符串添加到 0 ($a += 0;) ... 你的答案开始的方式我认为你比这里的其他人更好
  • 错误答案.. 如果数字有千位分隔符,则会失败
【解决方案2】:

试试rtrim:

$number = rtrim($number, "0");

如果您有一个以 0 结尾的十进制数(例如 123.000),您可能还希望删除 小数分隔符,这可能会因不同而异使用的语言环境。要可靠地删除它,您可以执行以下操作:

$number = rtrim($number, "0");
$locale_info = localeconv();
$number = rtrim($number, $locale_info['decimal_point']);

这当然不是万无一失的解决方案,也可能不是最好的解决方案。如果您有一个像 12300.00 这样的数字,它不会从整数部分删除尾随的 0,但您可以根据您的特定需要对其进行调整。

【讨论】:

  • 就我而言,我执行了以下操作: rtrim(rtrim($number, "0"),".") 因为如果显示的是整数,我还必须删除小数(对于例如,这将显示数字 2.00、1.00、28.50、16.25 我想显示为 2、1、28.5、16.25,而不是 2.、1.、28.5、16.25)
  • 我喜欢这个解决方案,因为您可以保留使用 number_format 插入的逗号: rtrim(rtrim(number_format($number, 2), '0'), '.') 在我的情况下,我不需要担心像 100 这样的整数,因为我要从数据库中提取十进制值。
  • @Staysee 是否可以从数据库中提取一个十进制值,如下所示:"123.0000000"?现在你有什么?
  • 更新了答案以显示如何根据当前语言环境也删除小数点分隔符。
  • 假设你有一个类似".000"的字符串。我想您希望您的函数返回 "0" 而不是 ""
【解决方案3】:

如果您尝试修剪或其他字符串操作,您会遇到很多麻烦。试试这个方法。

$string = "37.422005000000000000000000000000";

echo $string + 0;

输出:

37.422005

【讨论】:

  • 优秀的解决方案。知道这是如何工作的吗?因为它确实有效
  • 这很简单。你从一个有很多尾随零的字符串开始。 PHP 无法将整数 0 添加到字符串中,因此它首先将字符串转换为数字类型,然后将 0 添加到它。你最终得到一个数字,而不是一个字符串。数字类型不能用于尾随零。您应该小心自动类型转换,但在这种情况下,它是完全可预测且安全的。
  • 哇!我想这就是“好得令人难以置信”的定义!就像有人已经观察到的那样,这可以做一点解释。
  • @IfediOkonkwo 谢谢。我已经在 cmets 中发布了解释。
  • @poring91 你不能将rtrim 的行为称为“数学上非法”。它不是数学函数,也不是对数字进行运算。这是一个对字符串进行操作的字符串函数,它正在做它应该做的事情。它只是不适合这种情况。
【解决方案4】:

您也可以使用floatval(val);

 <?php
 echo floatval( "37.422005000000000000000000000000" );
 ?>

结果

37.422005

【讨论】:

  • 我认为这不是最好的选择,但是,如果你要转换为浮点数,请不要使用floatval()。只需使用(float) 将其转换为浮点数即可。如果可能,请始终避免调用额外的函数。 floatval() 的用例是当您要将整个值数组转换为浮点数时,您可以调用 array_map('floatval', $someArray);
  • floatval(float) 都将我的数字转换为科学计数法.0E-7
【解决方案5】:

就我而言,我做了以下事情,在这里扩展了其他答案:

rtrim((strpos($number,".") !== false ? rtrim($number, "0") : $number),".");

因为如果显示的是整数,我还必须删除小数

例如,这将显示以下数字

2.00, 1.00, 28.50, 16.25 

作为

2, 1, 28.5, 16.25

而不是

2., 1., 28.5, 16.25

对我来说,这并没有正确显示它们。

如果遇到小数点,最新编辑还会通过仅修剪最右边的 0 来阻止诸如“100”之类的数字被 rtrim'ed 为 1。

【讨论】:

  • 在诸如“100”之类的数字上会失败(去掉重要的 0)。
  • 谢谢马克,解决方案已更新(尽管在您发表评论后 18 个月!)
  • 编辑了我的反对票。现在看起来很像my answer
  • 如果以".000"开头会怎样?
  • 完全符合您的预期。它将返回一个空字符串 - 因为您已经删除了零和小数位......这里的问题是原始请求是询问 STRING 操作,而不是使用实际数字。如果您需要它返回一个数值,您可以将(float)rtrim((strpos($number,".") !== false ? rtrim($number, "0") : $number),"."); 或简单地+0 转换为原始字符串。
【解决方案6】:

这些解决方案中的大多数将修剪数字中的有效数字,例如“100”(无尾随小数)。这是一个没有这个问题的简单解决方案:

function TrimTrailingZeroes($nbr) {
    if(strpos($nbr,'.')!==false) $nbr = rtrim($nbr,'0');
    return rtrim($nbr,'.') ?: '0';
}

我认为这涵盖了所有不同的场景。

>>> TrimTrailingZeroes('0')
=> "0"
>>> TrimTrailingZeroes('01')
=> "01"
>>> TrimTrailingZeroes('01.0')
=> "01"
>>> TrimTrailingZeroes('01.01')
=> "01.01"
>>> TrimTrailingZeroes('01.010')
=> "01.01"
>>> TrimTrailingZeroes('.0')
=> "0"
>>> TrimTrailingZeroes('.1')
=> ".1"
>>> TrimTrailingZeroes('.10')
=> ".1"
>>> TrimTrailingZeroes('3141592653589793.238462643383279502880000000000000000000000000000')
=> "3141592653589793.23846264338327950288"

【讨论】:

  • 字符串'.0000' 产生空字符串。我相信你会想要'0'
  • @Okonomiyaki3000 够公平的。固定。
【解决方案7】:

如果您想从末尾去除多余的零,但只去除某个小数位,这是一个有用的表达式(例如,0.30000 将显示 0.30,0.0003000 将显示 0.0003)。

preg_replace("/(?<=\\.[0-9]{2})[0]+\$/","",$number);

当然,{2} 控制小数位限制。

【讨论】:

  • +1 使用最复杂的方法来解决一个简单的问题 :-)
  • "0.0003000"不会转换为 "0.0003"。小数点后最多只能有 2 个非零数字。这个正则表达式甚至不匹配。如果这是你想要的结果,你最好使用number_format($x,2,'.','')
  • 不要对这样的事情使用正则表达式。尤其不要使用这么复杂的正则表达式。
【解决方案8】:

修剪尾随零,但只在小数点后 - 例如,我们不想将 100 -> 1 转换。如果后面只有零,它也会去除句点。

function trim_zeros($str) {
    if(!is_string($str)) return $str;
    return preg_replace(array('`\.0+$`','`(\.\d+?)0+$`'),array('','$1'),$str);
}

【讨论】:

  • 至少你已经考虑过一个几乎所有人都忽略的案例。不过,没有。
  • @Okonomiyaki3000 您对这个解决方案有何不满?你的不允许任意大的数字/高精度。
  • 也许只有我一个人,但我尽量避免使用 preg 函数,除非它们是绝对必要的。不过,如果您需要超过 14 位小数的精度,这可能是最好的解决方案。
  • @Okonomiyaki3000 正则表达式并不是很慢,除非您运行数千个。不过,我确实提出了另一个不需要它们的解决方案:stackoverflow.com/a/19777740/65387
【解决方案9】:

如果您想要一个接受最小和最大小数位数的解决方案,这应该可行:

/**
 * Displays up to 4 decimal places, with a minimum of 2 decimal places, trimming unnecessary zeroes
 *
 * @param mixed $number
 * @param int $minimumDecimals
 * @param int $maximumDecimals
 * @return string
 */
function rate_format($number, int $minimumDecimals = 2, int $maximumDecimals = 4): string
{
    $formatted = number_format($number, $maximumDecimals, '.', ',');
    $minimumLength = strpos($formatted, '.') + $minimumDecimals + 1;
    $extra = rtrim(substr($formatted, $minimumLength), "0");
    return substr($formatted, 0, $minimumLength) . $extra;
}


// rate_format("1.2500") returns "1.25"
// rate_format("1.2525") returns "1.2525"
// rate_format("1.25256") returns "1.2526"
// rate_format("1") returns "1.00"

这是硬编码以使用美国语言环境,但应该很容易针对其他语言环境进行调整。

【讨论】:

    【解决方案10】:

    您应该使用round function,它比replace 更能操纵数字。

    round('37.422005000000000000000000000000', 32); 
    //float(37.422005)
    
    round('-122.84095000000000000000000000000', 32); 
    //float(-122.84095)
    

    得到的四舍五入数字将基于您的precision(默认 14) 设置。

    【讨论】:

    • 奇怪的是,这实际上是一个viable solution,通过指定像32 这样的高精度,它可以防止提供的数字被四舍五入。 round('-122.84095000000000000000000000000', 32) = -122.84095 但是,由于它将值转换为实数,它仍然会遇到浮点问题,即在使用高 ini_set('precision', 32) 时转换字符串值。
    • 很好的解决方案,但在我的情况下它只适用于小数点后 4 位。对于 5,... 它显示 e
    【解决方案11】:

    删除尾随零 + 千位分隔符

    function specialFormat($number,  $decimals = 8)
    {
        return rtrim(rtrim(number_format($number, $decimals), '0'), '.');
    }
    

    input: 0.00000008 => output: 0.00000008
    input: 1560.1854500 => output: 1,560.18545
    input: 1560.00 => output: 1,560
    

    【讨论】:

    • 一个简单的解决方案,解释了许多其他答案没有的逗号分隔。
    • 性感代码就在这里
    【解决方案12】:

    对我来说,我需要进一步的解决方案来将指数值和简单数字(如 10000)转换为最后一个非零有效数字

    /* Convert any value to the least significant value */
    function toDecimal($val) {
    
      // Convert any exponential sign to proper decimals
      $val = sprintf("%lf", $val);
    
      if (strpos($val, '.') !== false) {
          $val = rtrim(rtrim($val, '0'), '.');
      }
    
      return $val;
    }
    
    // Test cases
    echo toDecimal(1000.000) . "\n";
    echo toDecimal(1E-5) . "\n";
    echo toDecimal(1E+5) . "\n";
    echo toDecimal(1234.56) . "\n";
    echo toDecimal(1234.5700) . "\n";
    echo toDecimal(1234000) . "\n";
    echo toDecimal(-1e10) . "\n";
    
    // Results
    1000
    0.00001
    100000
    1234.56
    1234.57
    1234000
    -10000000000
    

    【讨论】:

    • 没有。除了1E-5(与这个问题无关)之外,所有这些“测试”在不通过你的函数运行的情况下都会完全一样。
    【解决方案13】:

    您可以使用 rtrim() (http://www.php.net/manual/en/function.rtrim.php):

    rtrim( "37.422005000000000000000000000000" , "0" )
    

    只要确保有小数点即可。

    【讨论】:

    • IMO,rtrim() 是比 preg_replace() 更好的选择
    • @BobbyJack 但只是勉强。
    【解决方案14】:

    嗯,有趣。我用过这个:

    // remove leading zeros
    $output = ltrim ($output, "0");
    
    // remove trailing 0s.
    $temp=explode(".",$output);
    $temp[1]=rtrim($temp[1],"0");
    $output = $temp[0];
    if (!empty($temp[1])) $output.='.'.$temp[1];
    
    return $output;
    

    这会从第一个小数点后的数字中删除尾随的 0。否则像 100 这样的数字会变成 1。

    由于我在进行比较,因此使用浮动技术会导致问题。希望这有帮助吗?

    【讨论】:

      【解决方案15】:

      preg_replace 可以解决问题:

      $lat=preg_replace('/0+$/','',$lat);
      

      【讨论】:

      • -1 因为虽然这可行,但这不是正则表达式的好用例。
      • @Unkwntech 处理器过于密集,无法简化任务?
      • @Shad,只是矫枉过正。正则表达式通常不是答案,如果可以使用类型 (string/int/float) 操作,它可能会更快,并且将来不太容易出现问题。例如,将您的解决方案与 RobertPitt 的解决方案进行比较,如果 $lat 是 10,您的解决方案会发生什么,而 RobertPitt 的解决方案会发生什么?除了这些原因之外,还请考虑当不了解正则表达式的开发人员在尝试修复错误时遇到您的解决方案时会发生什么。
      • 还有一个不这样做的理由,请考虑以下字符串:"123.0000000"
      猜你喜欢
      • 2021-10-15
      • 1970-01-01
      • 2020-02-06
      • 2011-11-01
      • 2014-09-02
      • 2018-09-28
      • 2021-12-04
      • 1970-01-01
      • 2011-05-30
      相关资源
      最近更新 更多