【问题标题】:PHP (int) generates wrong numberPHP(int)生成错误的数字
【发布时间】:2018-03-29 13:40:11
【问题描述】:

我正在编写一个处理货币金额的 PHP 脚本,因此需要精确到 2 位小数。为此,我通过将用户输入乘以 100 将其转换为数字,然后将其转换为 int。这很好用,直到我最近发现一个数字在转换为 int 时会增加 1。

故障代码:

$number = (int)(str_replace(',','.',$_POST["input"])*100);

出现问题的数字是 2509,22(我住在荷兰,所以我们使用逗号作为小数,因此在上面的代码行中使用了 str_replace)。 这个值创建了整数 $number 250921,这显然是 1 太低了。 我知道 int 有限制,但据我所知,这个数字完全在这些限制之内......

【问题讨论】:

  • 为什么需要将其设为 int?这样做的目的是什么?这个 int 旁边会发生什么?
  • 我用它来确保输入不包含超过 2 个小数。如前所述,它是财务信息,这是为了防止用户在财务系统中输入小于可能的分数。
  • 改用 bcmath。除非您绝对确定输出并且根据您的代码判断,否则切勿对浮点数进行操作,我确定您不是。您可以在此处阅读有关浮点数精度的更多信息php.net/manual/en/language.types.float.php
  • 如果您使用的是财务值,那么您需要了解浮点表示在计算机上的局限性,以及转换为 int、floor、round 和 ceil 之间的区别
  • 感谢马克贝克!我想我不知道这首先创建了一个浮点数,以及它的确切含义。

标签: php casting integer


【解决方案1】:

当您将字符串乘以100 时,您会得到float,它的表示并不总是您所期望的,在本例中为250921.99999999997。看看它:

echo serialize(str_replace(',','.','2509,22')*100);

然后你转换为integer,它会截断分数以获得250921。见Is floating point math broken?

解决方案是删除逗号并按原样使用,并可选择转换为integer

$number = (int)str_replace(',', '', '2509,22');

对于用户输入过多小数的问题,您应该使用两个输入,一个用于整数,一个用于小数和/或限制/验证输入的格式是否正确。但是,您可以先格式化数字:

echo $number = (number_format(str_replace(',', '.', '2509,22'), 2, '.', '')*100);

【讨论】:

  • 好的,谢谢!我认为整数只是将其四舍五入。你知道我应该使用什么类型的投射来获得正确的数字吗?
  • 因为当用户点击一个按钮的次数过多(所以他在输入框中输入了 2509,222)时,将存储的数字会太高。
  • @Discoverer 1) 如果小数点后有超过两位数(或逗号:),则拒绝输入 2) 在继续之前向客户端提供值验证和/或允许撤消方法.用户可能无意中使用了“错误”分隔符输入了一个额外的数字。
【解决方案2】:

您可以使用正则表达式来匹配 int 和零 - 两位小数。
这不会进行任何转换,也不会相乘或强制转换。
它将被视为一个字符串,除了小数位数之外没有任何变化。

$input = "2509,2222222";
// Regex number comma number (zero - two)
Preg_match("/(\d+),*(\d{0,2})/", $input, $m);
Unset($m[0]); // remove full match

Echo implode("", $m); // implode parts

https://3v4l.org/MjcYV

【讨论】:

  • 问题是数字也应该允许用点而不是逗号输入。当然你也可以删除它,但是当用户输入错误的数量时(比如点击按钮一次太多的 2509,222),那么这个数量将是 2509222,这太高了。
  • 这确实可行。就个人而言,我认为我将使用 David Bubenik 建议的解决方案,因为这也允许输入不带任何小数的数字。用户的方式并不是都很精确,所以我试图让它尽可能灵活,但感谢您的建议!
  • @Discoverer 老兄。当您发布问题时,请发布我们帮助您所需的所有信息。你一直在添加信息,这真的很烦人。
  • 我没有编辑问题,所以我认为您指的是我对如何(或可以)输入数字的担忧。对此感到抱歉,我很新,但由于我使用了 $_POST int 问题,我想我认为输入的卫生在编码中是如此标准,以至于我忘了提早提及它。对此感到抱歉。
  • @Discoverer 我已经更新了一种无论您输入什么都将始终有效的方法(除非它不是数字)。而且它不会进行任何可能搞砸数字的转换
猜你喜欢
  • 2012-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-15
  • 1970-01-01
  • 2020-06-21
  • 2015-07-29
相关资源
最近更新 更多