【问题标题】:'for' loop and typecasting hell ! (PHP)'for' 循环和类型转换地狱! (PHP)
【发布时间】:2009-08-22 15:09:55
【问题描述】:

//matches[0] 保存一些 preg_match'ed 值

for($i=0;$i<count($matches[0]);$i++)
 {

  $price = $matches[0][$i]; //a**uto type casting to (float) returns 0 for $price. Tried it for values greater than 1 too.**
  //echo gettype($price);
  $price = $price + 0.01; **//Returns 0 + 0.01 instead of the right answer**
    //**even after removing the above statement it does not compare**
    if($price <= 1.50 && $price >= 1.00){ //because it should auto type cast to float, which it does no...
      echo "here";
        $price = $price+0.50;}
    //strcmp always returns a '1' where 1 is surely not expected (not equal)
    else if(strcmp($price,"1.50") > 0)  && strcmp($price,"2.00") < 0 ){
      echo "here 2";
        $price = $price+0.50;}   

 }

这不是因为 $price 是一个常数,因为它属于一个循环吗?

我正常地尝试了同样的事情,没有循环,它正确地进行了类型转换。

我在这里错过了什么吗?

【问题讨论】:

  • 生成$matches的代码是什么?特别是正则表达式会很有帮助。目前我最好的猜测是它有一些空格,所以 $price = trim($matches[0][$i]); 会有所帮助,但我怀疑这就是整个解决方案。
  • 正则表达式是:-
    preg_match_all("/(\d|\.)+/",$data,$matches);此外,修剪没有工作。好主意。
  • $data 是从文件中获取的
  • 因为 foreach 给出了同样的问题......所以我想也许 for 循环会解决它.....
  • 进一步,在代码的后面,在for循环中,我还使用了 $matches[0][$i] = str_replace(".","\.",$matches[0][ $i]); //用于转义“。” $data = preg_replace("/".$matches[0][$i]."/",$price,$data,1);但它给了我这个错误“警告:preg_replace() [function.preg-replace]: Unknown modifier 'g' in”$matches[0][$i] has 1.80 as it's vlaue

标签: php loops for-loop


【解决方案1】:

我发现的东西不一定能解决整个问题:

永远不要比较浮点数的不等式。

var_dump(0.7 + 0.1 == 0.8);

输出false。不开玩笑。

这是因为它是 无法表达一些分数 用十进制表示法 位数。例如,1/3 英寸 十进制形式变为 0.3。

如果需要更高的精度,则 arbitrary precision math functionsgmp 函数可用。

来源:PHP: Floating point numbers查看警告部分

另外,您可以使用 PHP 的 SimpleXML 而不是手动 preg_matching 标签。

【讨论】:

  • 感谢您的资源,但那里的任何功能都不起作用。
  • 发生了什么是 $price 首先是一个字符串,但是一旦它转换为浮点数,它就会重新初始化为'0'。
  • "如果字符串以有效的数字数据开头,这将是使用的值。否则,该值将为 0(零)。"嗯......进一步研究......us3.php.net/manual/en/…
  • 您考虑过使用 SimpleXML 吗? (添加到我的答案中)
  • $price 变量是如何声明的?
【解决方案2】:

$matches[0][$i] 包含整个表达式,包括标签。要引用 ***1***st 捕获(括号中的内容),请改用:

$price = $matches[1][$i];

或者更好的是,将您的 for 循环替换为 foreach

foreach ($matches[1] as $price)

另外,看看assignment operators,看看如何大大简化一些表达式,例如

$price += 0.50;

【讨论】:

    【解决方案3】:

    您可能对SimpleXML 感兴趣以从您的xml 字符串/文件/源(如前所述)和BC Math functions 中获取值,它允许您绕过大多数精度限制。

    <?php
    $items = new SimpleXMLElement(getXml());
    // setting bcmath's default scale to two (digits after the .)
    bcscale(2); 
    
    foreach( $items as $item ) {
      $price = bcadd($item->price, '0.01');
      echo $price, " -> ";
      if ( -1<bccomp($price, '1.00') && 1>bccomp($price, '1.50') ) {
        $price = bcadd($price, '0.50');
        echo 'a) price+0.50=', $price, "\n";
      }
      else if ( 0<bccomp($price, '1.50') && 1>bccomp($price, '2.00') ) {
        $price = bcadd($price, '0.50');
        echo 'b) price+0.50=', $price, "\n";
      }
      else {
        $price = bcadd($price, '0.10');
        echo 'c) price+0.10=', $price, "\n";
      }
    }
    
    function getXml() {
      return '<foo>
        <item>
          <description>a</description>
          <price>1.48</price>
        </item>
        <item>
          <description>b</description>
          <price>1.49</price>
        </item>
        <item>
          <description>c</description>
          <price>1.50</price>
        </item>
        <item>
          <description>d</description>
          <price>1.99</price>
        </item>
        <item>
          <description>e</description>
          <price>2.00</price>
        </item>
      </foo>';
    }
    

    打印

    1.49 -> a) price+0.50=1.99
    1.50 -> a) price+0.50=2.00
    1.51 -> b) price+0.50=2.01
    2.00 -> b) price+0.50=2.50
    2.01 -> c) price+0.10=2.11
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-07-30
      • 2018-06-26
      • 2012-11-25
      • 2015-01-06
      • 2010-11-19
      • 2014-11-22
      • 1970-01-01
      相关资源
      最近更新 更多