views:

155

answers:

3

//matches[0] holds some preg_match'ed values

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;}   

 }

Does this not work because $price is a constant as it belongs to a loop ?

I tried the same thing normally, without the loop, and it typecasts properly.

Am I missing something here ?

+2  A: 

Something I found which doesn't necessarily solve the entire thing:

Never compare floats for inequality.

var_dump(0.7 + 0.1 == 0.8);

outputs false. No kidding.

This is due to the fact that it is impossible to express some fractions in decimal notation with a finite number of digits. For instance, 1/3 in decimal form becomes 0.3.

If higher precision is necessary, the arbitrary precision math functions and gmp functions are available.

Source: PHP: Floating point numbers check out the warning part

Also, you could use PHP's SimpleXML instead of preg_matching the tags manually.

Randell
Thanks for the resource, but none of the functions there worked.
What is ahppening is that $price is first a string, But as soon as it is converted to a float, it is re-intialized to '0'.
"If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero)."hm...looking further into it.....http://us3.php.net/manual/en/language.types.string.php#language.types.string.conversion
Have you considered using SimpleXML? (added to my answer)
Randell
How was the `$price` variable declared?
Randell
will try using it .... seems like DOM ....
declared it as both $price = "0.00"; and as $price = 0.00None seem to work.
Try declaring as `$price = 0.00` and explicitly cast `$matches[0][$i]` like this: `(float) $matches[0][$i]` then you'll have `$price = (float) $matches[0][$i]`.
Randell
Nope. Still reinitializes to 0 in case of explicit typecast...Thanks for the help Randell.
I suggest that you debug this thing by divide and conquer. Remove working codes until you are able to isolate the non-working code. Then start from there.
Randell
It has something to do with the preg_match. This is because when I overwrite $matches values like so,$matches[0][0] = "5.51";$matches[0][1] = "1.80";then the code works....
Someone please slap me. I made an old mistake of not looking at the page source. What was outputted to the browser was $matches[0][0] = '<price>5.51</price>' but the browser showed only 5.51. This was due to the regular expression. slap slap slap.....
*slap*
Randell
Hey, you might want to post your answer as the correct answer so as to finish this thread.
Randell
A: 

You may be interested in SimpleXML to get the values from your xml string/file/source (as mentioned before) and the BC Math functions which allows you to ship around most precision limitiations.

<?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>';
}

prints

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
VolkerK
+1  A: 

$matches[0][$i] contains the whole expression, including the tags. To refer to the 1st capture (the thing in parenthesis) use this instead:

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

Or better yet, replace your for loop with foreach:

foreach ($matches[1] as $price)

Also, take a look at assignment operators, see how you can greatly simplify some expressions such as

$price += 0.50;
Josh Davis