Jump to content

PLEASE HELP! Issues with floating point addition / comparison...


crackers8199

Recommended Posts

Hello!  I've got a major issue on my hands here and it's causing me to pull my hair out...

 

I've written a parser to parse a CSV file that has three fields per line.  The third field is always a number - I want to add up all of these values, and then check to see if it equals 100 before proceeding.  If it does not equal 100, I want to print a message and exit.

 

Here's the issue - this works perfectly fine for 100 lines in the file to be parsed or less.  As soon as I go over 100 (and I mean immediately, it happens for 101 lines and up), the script breaks.  Even though the numbers in the last field all add up to 100, for some reason the if statement is tripped, a message is displayed and the script exits.  I know for a fact that they're adding up to 100 because I had several echo statements in there displaying as such - but as soon as the file has more than 100 lines, even though they add up to 100, it does what's inside the if statement and exits.

 

I cannot for the life of me figure this out.  Please help!!  I can't deal with this anymore, I've been looking at it for 6 hours straight, and nothing I have tried has worked.  Here is the code - the contents of the file are in $importContents, each element in the array is a line in the file:

 

$firstdisp = true;

$query = array();

$counter = 0;

$totalPCT = floatval(0.0);

 

foreach($importContents as $indLink) {

 

$indLinkSep = explode(", ", $indLink);

$indFieldCount = count($indLinkSep);

 

if($indFieldCount != $fieldCount) {

 

// invalid format, all rows must have same number of fields, must exit here

 

}

 

if($fieldCount == 3)

$pct = floatval($indLinkSep[2]);

else

($firstdisp) ? $dispPCT = 100 : $dispPCT = 0;

 

$firstLink = false;

 

$totalPCT = floatval($totalPCT) + floatval($dispPCT);

 

}

 

$PCTcheck = 100.0;

 

if(floatval($totalPCT) != floatval($PCTcheck)) {

 

// percentages must equal 100, must exit here

echo "total percentages = $totalPCT, must equal 100";

exit;

 

 

 

}

Well, it would have been helpful if you had uploaded the data file. But i am noticing some things:

 

"but as soon as the file has more than 100 lines, even though they add up to 100, it does what's inside the if statement and exits" Which if statement

 

Where is $fieldcount set?

 

What is the purpose of $firstLink?

 

This script really isn't making any sense to me.

Alright...here's the entire script (the relevant part, anyway):

 

// ------ SCRIPT BELOW THIS LINE -----

 

else if($_GET[$GETVAR_ACTION] == "upload") {

 

$importContents = @file($_FILES['userfile']['tmp_name']);

 

$indLinkSep = explode(", ", $importContents[0]);

$fieldCount = count($indLinkSep);

 

if($fieldCount != 2 && $fieldCount != 3) {

 

// invalid number of fields, must exit here

exit;

 

 

}

 

require($SERVERINFO_LOCATION);

$table = $_COOKIE[$COOKIENAME_USERNAME] . $CONTENT_EXTENSION;

 

MYSQL_CONNECT($server, $user, $password) or die(displayErrorPage("Server (" . $server . ") unreachable", true));

MYSQL_SELECT_DB($database) or die(displayErrorPage("Database (" . $database . ") does not exist", true));

 

if($_POST['truncTable'] == "on") {

 

$query = "truncate table $table";

mysql_query($query) or die("cannot remove current links");

 

echo "successfully removed current links\n\n";

 

}

 

$firstLink = true;

$query = array();

$counter = 0;

$totalPCT = floatval(0.0);

 

foreach($importContents as $indLink) {

 

$indLinkSep = explode(", ", $indLink);

$indFieldCount = count($indLinkSep);

 

if($indFieldCount != $fieldCount) {

 

// invalid format, all rows must have same number of fields, must exit here

exit;

 

 

}

 

$anchortext = $indLinkSep[0];

$url = $indLinkSep[1];

 

if($fieldCount == 3)

$dispPCT = floatval($indLinkSep[2]);

else

($firstLink) ? $dispPCT = 100 : $dispPCT = 0;

 

$query[$counter++] = array("textline" => $indLink, "query" => "insert into $table($CONTENTDB_ANCHORTEXT, $CONTENTDB_URL, $CONTENTDB_PERCENTAGE) values('$anchortext', '$url', '$dispPCT')");

 

$firstLink = false;

 

}

 

$PCTcheck = 100.0;

 

if(floatval($totalPCT) != floatval($PCTcheck)) {

 

// percentages must equal 100, must exit here

echo "total percentages = $totalPCT, must equal 100";

exit;

 

}

 

foreach($query as $indQuery) {

 

mysql_query($indQuery['query']) or die("cannot import link: " . $indQuery['textline']);

echo "import successful: " . $indQuery['textline'];

 

}

 

mysql_close();

 

exit;

 

}

 

// ------ and here's a few lines from the data file, below this line ------

 

test1, test, 1

test2, test, 1

test3, test, 1

test4, test, 1

test5, test, 1

 

// -----------------------------

 

Essentially what happens is, at seemingly random times (but ONLY when there are more than 100 lines in the data file), the if statement that checks to see if the sum of the third field on each line is equal to 100, even if the sum is equal to 100.  I end up with the following output...

 

total percentages = 100, must equal 100

 

This obviously doesn't make sense, because if the total percentage is equal to 100 then it should not be entering that if statement...

OK, well something's not right. First you set the value of $totalPCT here:

$totalPCT = floatval(0.0);

 

Then you set the value of $PCTcheck here:

$PCTcheck = 100.0;

 

Then I don't see anywhere in the script that the value of those two variables are changed. So, no matter what, this comparrison will always evaluate to true (i.e. they are not equal). So what's the point?

if(floatval($totalPCT) != floatval($PCTcheck)) {

 

The part that is confusing is why the echo statement is showing the value of $totalPCT as 100.

I'm not trying to be rude, but as I stated before the logic in your script is hard to follow and the comments you have do not adequately explain what needs to be explained. You also left out a key piece of code when you stated you had posted "the entire script (the relevant part, anyway)". Which makes me wonder what else may have been omitted. So, I'm not willing to invest more time until I know all the facts are present (i.e. the entire script and a test file).

 

Anyway, here is what I would do to figure out the problem. There is definitely something going on with the values somewhere. So, just echo the value of all the aplpicable variables at every step. Maybe, the code below will help you get started.

 

<?php

echo "<table>";  //<===== NEW LINE

   foreach($importContents as $indLink) {

      $indLinkSep = explode(", ", $indLink);
      $indFieldCount = count($indLinkSep);

      if($indFieldCount != $fieldCount) {

         // invalid format, all rows must have same number of fields, must exit here
         exit;
      }

      $anchortext = $indLinkSep[0];
      $url = $indLinkSep[1];

      if($fieldCount == 3)
         $dispPCT = floatval($indLinkSep[2]);
      else
         ($firstLink) ? $dispPCT = 100 : $dispPCT = 0;

      $query[$counter++] = array("textline" => $indLink, "query" => "insert into $table($CONTENTDB_ANCHORTEXT, $CONTENTDB_URL, $CONTENTDB_PERCENTAGE) values('$anchortext', '$url', '$dispPCT')");

      echo "<tr>";  //<===== NEW LINE
      echo "<td>$indLink</td>";  //<===== NEW LINE
      echo "<td>$indFieldCount</td>";  //<===== NEW LINE
      echo "<td>$anchortext</td>";  //<===== NEW LINE
      echo "<td>$url</td>";  //<===== NEW LINE
      echo "<td>$dispPCT</td>";  //<===== NEW LINE
      echo "<td>$firstLink</td>";  //<===== NEW LINE
      echo "</tr>";  //<===== NEW LINE

      $firstLink = false;
   }
   echo "</table>";  //<===== NEW LINE

   $PCTcheck = 100.0;

   if(floatval($totalPCT) != floatval($PCTcheck)) {
      echo "totalPCT [$totalPCT]<br>totalPCT Float [".floatval($totalPCT)."]<br>";  //<===== NEW LINE
      echo "PCTcheck [$PCTcheck]<br>PCTcheck Float [".floatval($PCTcheck)."]<br>";  //<===== NEW LINE
      // percentages must equal 100, must exit here
      echo "total percentages = $totalPCT, must equal 100";
      exit;
   }
?>

Archived

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

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.