Jump to content
  • Checkout
  • Login
  • Get in touch

osCommerce

The e-commerce.

PHP Math bug, big problem


MreSailor

Recommended Posts

There's a bug in PHP 4.4.2 on my server that has really gummed up the works trying to use the CCGV5.16 and download controller. It's also documented 4.3.2, 4.3.3 & 4.3.4 so far as I've found.

 

Select 10 separate items for download at 4.95 each and apply a $49.50 gift coupon and the resulting total is 7.105427357601E-15. (nice, eh?)

 

Select any other combination to get 49.50 as a total apply the coupon and it seems to work fine (like 10 single 4.95 downloads). The coupon applys and the total is 0.00 as expected.

 

This has been referenced on Google as well. Search " php 7.105427357601E-15 ". I had to do some major hacks to get it to work properly for a deadline but need to go back and clean up the code to fix this.

 

Anyone else come across this and find a solution thats perminant?

Link to comment
Share on other sites

I've seen a reference on the PHP site to string rounding issues and errors with comparisons. Any help would be appreciated. The round fuction doesn't seem to change it neither does casting the varibles to Integers?????

Link to comment
Share on other sites

one of the ccgv contribution's submissions targets the rounding problem. Have you deployed that? It's item-4 of the latest update.

Link to comment
Share on other sites

Its not a bug in php its the acceptable precision of floating point numbers.

 

You can see it happens in other languages like VC++

 

http://eggheadcafe.com/ng/microsoft.public.../post271572.asp

 

I dont have an older version of php to see if it always existed but if it was internally fixed before then it would cause errors for people trying to calculate scientific formulas. In the floating point world 0 != 0.

 

Unfortunately none of the functions like sprintf or number_format handle it correctly, unless -0.00 is acceptable to you, so I guess you need to hack it.

 

if ($resultB < 0.000) $resultB = 0;

 

I would say the php bug is that number_format(-7.105427357601E-015, 2) gives -0.00.

 

Dave...

 

<?php

//Output
//Result A: 0
//Result B: -7.105427357601E-015
//Result B: -7.09
//Result B: -0.00
//Result B: -0.00

//Result B: 0
//Result B: 0.00
//Result B: 0.00

$resultA = ((6.00 * 5.95) - (5.95 + 5.95 + 5.95 + 5.95 + 5.95 + 5.95));

$resultB = ((7.00 * 5.95) - (5.95 + 5.95 + 5.95 + 5.95 + 5.95 + 5.95 + 5.95));

echo "Result A: ".$resultA."\n";
echo "Result B: ".$resultB."\n";
echo "Result B: ". tep_round($resultB,2) ."\n";
echo "Result B: ". number_format($resultB,2) ."\n";
echo "Result B: ". sprintf("%.2f", $resultB) ."\n";

if ($resultB < 0.000) $resultB = 0;

echo "Result B: ". tep_round($resultB,2) ."\n";
echo "Result B: ". number_format($resultB,2) ."\n";
echo "Result B: ". sprintf("%.2f", $resultB) ."\n";


 function tep_round($number, $precision) {
if (strpos($number, '.') && (strlen(substr($number, strpos($number, '.')+1)) > $precision)) {
  $number = substr($number, 0, strpos($number, '.') + 1 + $precision + 1);

  if (substr($number, -1) >= 5) {
	if ($precision > 1) {
	  $number = substr($number, 0, -1) + ('0.' . str_repeat(0, $precision-1) . '1');
	} elseif ($precision == 1) {
	  $number = substr($number, 0, -1) + 0.1;
	} else {
	  $number = substr($number, 0, -1) + 1;
	}
  } else {
	$number = substr($number, 0, -1);
  }
}

return $number;
 }

?>

Link to comment
Share on other sites

Thanks,

 

That helped out alot, I'm suprised this hasn't come up before, or if so I couldn't find in in the forum archives.

 

If I can figure where the grand total is calculated after applying the CCGV discounts to zero it out if it's not correct I'll be home free. Any ideas?

 

I found one spot but it only helps in order process and confimation the bad value still writes into the order history database.

 

Its not a bug in php its the acceptable precision of floating point numbers.

 

You can see it happens in other languages like VC++

 

http://eggheadcafe.com/ng/microsoft.public.../post271572.asp

 

I dont have an older version of php to see if it always existed but if it was internally fixed before then it would cause errors for people trying to calculate scientific formulas. In the floating point world 0 != 0.

 

Unfortunately none of the functions like sprintf or number_format handle it correctly, unless -0.00 is acceptable to you, so I guess you need to hack it.

 

if ($resultB < 0.000) $resultB = 0;

 

I would say the php bug is that number_format(-7.105427357601E-015, 2) gives -0.00.

 

Dave...

 

<?php

//Output
//Result A: 0
//Result B: -7.105427357601E-015
//Result B: -7.09
//Result B: -0.00
//Result B: -0.00

//Result B: 0
//Result B: 0.00
//Result B: 0.00

$resultA = ((6.00 * 5.95) - (5.95 + 5.95 + 5.95 + 5.95 + 5.95 + 5.95));

$resultB = ((7.00 * 5.95) - (5.95 + 5.95 + 5.95 + 5.95 + 5.95 + 5.95 + 5.95));

echo "Result A: ".$resultA."\n";
echo "Result B: ".$resultB."\n";
echo "Result B: ". tep_round($resultB,2) ."\n";
echo "Result B: ". number_format($resultB,2) ."\n";
echo "Result B: ". sprintf("%.2f", $resultB) ."\n";

if ($resultB < 0.000) $resultB = 0;

echo "Result B: ". tep_round($resultB,2) ."\n";
echo "Result B: ". number_format($resultB,2) ."\n";
echo "Result B: ". sprintf("%.2f", $resultB) ."\n";
 function tep_round($number, $precision) {
if (strpos($number, '.') && (strlen(substr($number, strpos($number, '.')+1)) > $precision)) {
  $number = substr($number, 0, strpos($number, '.') + 1 + $precision + 1);

  if (substr($number, -1) >= 5) {
	if ($precision > 1) {
	  $number = substr($number, 0, -1) + ('0.' . str_repeat(0, $precision-1) . '1');
	} elseif ($precision == 1) {
	  $number = substr($number, 0, -1) + 0.1;
	} else {
	  $number = substr($number, 0, -1) + 1;
	}
  } else {
	$number = substr($number, 0, -1);
  }
}

return $number;
 }

?>

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...