/    Sign up×
Community /Pin to ProfileBookmark

php math zero error; produces: -4.54747350886E-13

I ran into an interesting math error
The actual code producing the error:

[code=php]<?php
// Calculate Balance

$q = 0;
while ($q < $i){
$subtotal = $subtotal + $payment_deposit_[$q];
$q++;
}
settype($thousand, ‘double’); $thousand = 1000.00;
settype($pmt, ‘double’);

$pmt = $thousand – $subtotal;

?>[/code]

when … $payment_deposit_[$q] … is 1000
$pmt produces … (-4.54747350886E-13) …
and is supposed to produce … 0 …

I had to add: if($pmt < 0){$pmt = 0;} just to get it to work properly.
I was wondering why it was doing this. I tried using gettype and settype to
troubleshoot the problem without success.

to post a comment
PHP

9 Comments(s)

Copy linkTweet thisAlerts:
@SrWebDeveloperFeb 01.2010 — Since PHP 4.2.0 use "float" instead of the deprecated "double".

I found the rest of it confusing and unhelpful since you're not echoing each array value to see what numbers are really involved.
Copy linkTweet thisAlerts:
@anothenauthorFeb 01.2010 — I really didn't want to post too much code here. The section of code is...

[code=php]<?php
// Begin main display
// retrieve all records from $table_name sort asc item

include("config_credit_card.php");


// create the SQL statement
$sql = "SELECT *FROM $table_name ORDER BY item DESC";
$result = mysql_query($sql, $conn) or die(mysql_error());

// define temporary variables as arrays
$item_ = array();
$date_ = array();


// $check_number_ = array();


$description_ = array();
$account_ = array();
$memo_ = array();
$payment_deposit_ = array();
$balance_ = array();
$user_ = array();
$confirm_ = array();

$i = 0;

while ($newArray = mysql_fetch_array($result)) {
$item_[$i] = $newArray['item'];
$date_[$i] = $newArray['date'];


// $check_number_[$i] = $newArray['check_number'];


$description_[$i] = $newArray['description'];
$account_[$i] = $newArray['account'];
$memo_[$i] = $newArray['memo'];
$payment_deposit_[$i] = $newArray['payment_deposit'];
$balance_[$i] = $newArray['balance'];
$user_[$i] = $newArray['user'];
$confirm_[$i] = $newArray['confirm'];

$i++;

}
?>




<?php
// Calculate Balance

$q = 0;
while ($q < $i){
$subtotal = $subtotal + $payment_deposit_[$q];
settype($payment_deposit_[$q], 'float');
// /////////////////////// temporary troubleshooting ///////////////////
echo $payment_deposit_[$q]; echo " : ";
// ////////////////////////////////////////////////////////////////////////
$q++;
}
settype($thousand, 'float'); $thousand = 1000.00;
settype($pmt, 'float');

$pmt = $thousand - $subtotal;
// if($pmt < 0){$pmt = 0;}


?>





<table border="1" width="100&#37;">
<tr><td colspan="5" align="right">Balance</td>
<td align="right"><?php echo $subtotal; ?></td>
<td align="right">(<?php echo $pmt; ?>)</td></tr>
<tr>
<th width="10">Item</th>
<th width="60">Date</th>

<th width="200">Description</th>
<th width="75">Account</th>
<th width="75">Memo</th>

<th width="125">Payment/Deposit Amount</th>

<th width="10">*</th>

</tr>




<form method="post" action="<?php $_SERVER[PHP_SELF]; ?>">

<tr>
<td>

<td><input type="text" size="10" name="date" value="<?php echo $date_formatted; ?>">


<td><input type="text" size="30" maxlength="100" name="description">
<td>

<select name="account">
<option selected value="1"> <?php echo $account_name[1]; ?> </option>
<option value="101"> <?php echo $account_name[2]; ?> </option>
<option value="102"> <?php echo $account_name[3]; ?> </option>
<option value="103"> <?php echo $account_name[4]; ?> </option>



</select>

<?php
// Set up accounts
//

?>


<td><input type="text" size="10" maxlength="50" name="memo">

<td align="right"><input type="text" size="6" maxlength=10" name="payment_deposit">
<input type="hidden" name="insert_values" value="1">
<input type="submit" value="Enter">

<td>


</tr>

</form>





<?php
// display array

$p = 0;
while ($p < $i){
?>

<?php
// switch account contents 1 = Wingfoot, 101 = Fuel, 102=service, 103=telephone
switch ($account_[$p]){
case "1":
$account_text = "Payment";
break;

case "101":
$account_text = "Fuel";
break;

case "102":
$account_text = "Service";
break;

case "103":
$account_text = "Telephone";
break;
}

?>

<tr>
<td><?php echo $item_[$p]; ?>
<td><?php echo $date_[$p]; ?>

<td><?php echo $description_[$p]; ?>
<td><?php echo $account_text; ?>
<td><?php echo $memo_[$p]; ?>

<!-- comment out <td align="right"><?php echo $payment_deposit_[$p]; ?> -->
<td align="right"><?php printf("%.2f" , $payment_deposit_[$p]); ?>

<td>

<?php
// confirm section
// if $confirm[$p] = "1" then display "*"
// else input button "confirm"
if($confirm_[$p] == 1){
?>
*
<?php
} else { ?>
<form style="margin:0;" method="post" action="<?php $_SERVER[PHP_SELF]; ?>">
<input type="hidden" name="item_number" value="<?php echo $item_[$p]; ?>">
<input type="hidden" name="confirm_" value="1">
<input type="submit" value="Confirm">
</form>
<?php } ?>



</tr>

<?php
$p++;
}

// reset index counters to 0
$p = 0;
$i = 0;
?>






</table>[/code]


and is producing:

[ATTACH]13446[/ATTACH]

(edited to save upload limits)

[upl-file uuid=92cf24a9-cb73-4e99-aff2-dc57aa2922bc size=32kB]zero_error.JPG[/upl-file]
Copy linkTweet thisAlerts:
@SrWebDeveloperFeb 01.2010 — I didn't ask you to post code, actually.

[code=php]$pmt = $thousand - $subtotal;[/code]Please see my code below to echo all 3 variables so we can see those values, specifically. All the other code doesn't seem relevant to the issue at hand. I did check out the debugging attachment and the numbers are floated properly, some positive and some negative.

Change the "Calculate Balance" section to this, as an experiment, I moved a few things around to ensure the variables are cast before being modified in your while statement and added the debugging I need to see:

[code=php]$q = 0;
settype($subtotal, 'float');
while ($q < $i){
settype($payment_deposit_[$q], 'float');
$subtotal += $payment_deposit_[$q];
$q++;
}
settype($thousand, 'float');
$thousand=1000;
settype($pmt, 'float');
$pmt = $thousand - $subtotal;
echo "<br />Payment: $pmt $thousand=$thousand $subtotal=$subtotal";
[/code]
[COLOR=#000000][COLOR=#007700]



-jim



[/COLOR]
[/COLOR]
Copy linkTweet thisAlerts:
@anothenauthorFeb 01.2010 — 
...
[code=php]$q = 0;
settype($subtotal, 'float');
while ($q < $i){
settype($payment_deposit_[$q], 'float');
$subtotal += $payment_deposit_[$q];
$q++;
}
settype($thousand, 'float');
$thousand=1000;
settype($pmt, 'float');
$pmt = $thousand - $subtotal;
echo "<br />Payment: $pmt $thousand=$thousand $subtotal=$subtotal";
[/code]
[COLOR=#000000][COLOR=#007700]



-jim



[/COLOR]
[/COLOR]
[/QUOTE]


produces:

Payment: -4.54747350886E-13 $thousand=1000 $subtotal=1000

I don't get it. Why on earth would it produce such a way off number?

I tried something else, I echo-ed all the contents of the array, just to see.

Most of the contents are a negative number, but it seems to me that they should not effect anything.

$q = 0;

settype($subtotal, 'float');

while ($q < $i){

settype($payment_deposit_[$q], 'float');

$subtotal += $payment_deposit_
[$q];

echo $payment_deposit_[$q]; echo " : ";

$q++;

}

settype($thousand, 'float');

$thousand=1000;

settype($pmt, 'float');

$pmt = $thousand - $subtotal;

echo "<br />Payment: $pmt $thousand=$thousand $subtotal=$subtotal";


438.8 : -13.99 : -21.11 : -27.4 : -149.38 : -21.33 : -64.07 : -86.57 : -54.95 : 525.41 : -87.62 : -19.44 : -34.54 : -23.04 : -23.29 : -30.23 : -13.41 : -10.77 : -15.99 : -115.13 : -48.49 : 582.08 : -21.22 : -25.92 : -27.89 : -28.43 : -26.65 : -25.89 : -4 : -33.72 : -17.51 : -31.55 : -129.34 : -28.21 : -23.6 : -32.42 : -26.14 : -18.47 : -24.76 : -24.85 : -23.04 : -32.99 : -30.45 : -48.49 : 292.88 : -28.44 : -28.15 : -27.92 : -26.51 : -28.87 : -14.06 : -30.43 : -32.83 : -48.49 : -27.18 : 299.49 : -9.06 : -27.68 : -26.11 : -31.6 : -17.47 : -26.8 : -15.95 : -24.09 : -13.22 : -59 : -48.51 : 168.91 : -21.46 : -25.66 : -62.83 : -3.4 : -55.56 : 379.04 : -18 : -58.55 : -129.34 : -58.94 : -58.47 : 223.61 : -3.67 : -52.07 : -47.16 : -53.92 : -60.74 : -61.79 : 621.58 : -63.74 : -509.09 : -25.49 : -23.26 : 250 : 204.3 : 193.28 : 165.7 : -18.26 : -47.16 : -293.1 : -29.74 : -13.94 : -13.64 : -16.84 : -26.08 : -20.41 : -27.66 : -22.48 : -16.75 : -61.6 : -61.6 : 237.43 : -31.91 : -34 : -25.98 : -31.7 : -13.05 : -25.72 : -13.55 : -23.03 : -20.42 : -18.07 : 637.64 : -98.61 : -40.97 : -0.14 : -157.62 : -36.22 : -49.78 : -29.75 : -9.73 : -59.16 : -6.38 : -32.78 : -21.97 : -28.17 : -63.36 : 59.79 : 365.8 : -47.04 : -17.5 : -12.75 : -31.63 : -11.3 : -31.23 : -14.05 : -33.05 : -27.78 : -29.96 : -28.12 : -3.24 : -1.19 : -3.24 : -35.9 : -33.78 : -31.47 : -32.32 : 367.11 : -32.83 : -5 : -33.59 : -13.33 : -31.3 : -14.95 : -26.95 : -183.04 : -47.04 : -26.12 : 314.51 : -28.21 : -29.61 : -30.66 : -13.76 : -24.08 : -11.11 : 450 : 57.74 : -27.1 : -47.04 : -9.95 : 56.84 : -0.75 : -9.95 : -46.89 : 152.79 : 0 : 0 : 0 : -9.95 : -25.41 : -45.34 : -32.17 : 113.71 : -39.92 : -40.2 : -46.77 : -7.95 : -18.79 : 98.37 : -42.41 : -38.44 : -17.52 : 37.95 : 50 : -38.54 : -5 : 105.76 : -22.3 : 50 : -22.11 : -38.04 : -47.01 : -10.03 : -18.31 : -21.41 : -20.96 : 300 :

Payment: -4.54747350886E-13 $thousand=1000 $subtotal=1000
Copy linkTweet thisAlerts:
@NogDogFeb 01.2010 — Most likely you are running into floating point precision issues. From http://www.php.net/manual/en/language.types.float.php#language.types.float.casting:
Warning

Floating point precision

It is typical that simple decimal fractions like 0.1 or 0.7 cannot be converted into their internal binary counterparts without a small loss of precision. This can lead to confusing results: for example, floor((0.1+0.7)*10) will usually return 7 instead of the expected 8, since the internal representation will be something like 7.9.

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.

So never trust floating number results to the last digit, and never compare floating point numbers for equality. If higher precision is necessary, the arbitrary precision math functions and gmp functions are available.[/quote]


-4.54747350886E-13 is 0.00000000000045...., which is very, very close to zero for most purposes. You may simply need to apply round() to such values to the desired degree of precision.
Copy linkTweet thisAlerts:
@anothenauthorFeb 01.2010 — Most likely you are running into floating point precision issues. From http://www.php.net/manual/en/language.types.float.php#language.types.float.casting:


-4.54747350886E-13 is 0.00000000000045...., which is very, very close to zero for most purposes. You may simply need to apply round() to such values to the desired degree of precision.[/QUOTE]


thx ng

YES!! round() is what I'm needing. Hadn't thought of that.

Thx for the link, that helped to explain why, and that is what really baffled me.
Copy linkTweet thisAlerts:
@SrWebDeveloperFeb 01.2010 — Excellent. In my mind to see the problem much more clearly I'm glad we took the time to change the code and properly debug all 3 key values. It just confirms what you originally said, lacking verified numbers and actual code at the time (plus changing to float). Funny, it's pretty darned obvious now!

Thanks, NogDog for assisting.

-jim
Copy linkTweet thisAlerts:
@NogDogFeb 02.2010 — No problem. First time I looked at this thread I didn't see it, as I skimmed over the problematic number and didn't notice the negative exponent.
Copy linkTweet thisAlerts:
@anothenauthorFeb 02.2010 — Excellent. In my mind to see the problem much more clearly I'm glad we took the time to change the code and properly debug all 3 key values. It just confirms what you originally said, lacking verified numbers and actual code at the time (plus changing to float). Funny, it's pretty darned obvious now!

Thanks, NogDog for assisting.

-jim[/QUOTE]


Thx jim

yeah, it gets frustrating at times. My mistakes are usually something as simple as ";" or ?>

feels good to run across a real brain bender.
×

Success!

Help @anothen spread the word by sharing this article on Twitter...

Tweet This
Sign in
Forgot password?
Sign in with TwitchSign in with GithubCreate Account
about: ({
version: 0.1.9 BETA 5.21,
whats_new: community page,
up_next: more Davinci•003 tasks,
coming_soon: events calendar,
social: @webDeveloperHQ
});

legal: ({
terms: of use,
privacy: policy
});
changelog: (
version: 0.1.9,
notes: added community page

version: 0.1.8,
notes: added Davinci•003

version: 0.1.7,
notes: upvote answers to bounties

version: 0.1.6,
notes: article editor refresh
)...
recent_tips: (
tipper: @AriseFacilitySolutions09,
tipped: article
amount: 1000 SATS,

tipper: @Yussuf4331,
tipped: article
amount: 1000 SATS,

tipper: @darkwebsites540,
tipped: article
amount: 10 SATS,
)...