I recently received help on another site with a graphing problem, however I met strong resistance to re-compiling our web server to enable BCmath. The powers that be at my work say it is unnecessary and will only lead to problems when Apple releases a point update to Mac OSX Server.

Can what this guy wrote be changed and an alternative to using BCMath be found? The majority of it is inside these two functions.

bcscale(2); //this line is important. it should come before all calls to bc* functions.
/*	Gets the minimum of the range in which the discri falls */
function get_base($x){
	//divide by 10 and multiply by 10, so that
	//we can get rid of the digit at the 0.0x position.
	$r = bcdiv($x, '10');
	$r = bcmul($r, '10');
	//if the number is less than 0, reduce it by 0.1
	if (bccomp($x, '0') == -1)
		$r = bcsub($r, '0,1');

return $r;
}

function get_ranges($mmin, $mmax){
	$min = get_base($mmin);
	if (bccomp($min, $mmin) > 0)
		$min = bcsub($min, '0.1');
	$max = get_base($mmax);
	// a positive number is rounded to off 0.x position.
	// if number is something like 0.51 we need 0.60 as max to
	// fit 0.51 in the range of 0.50-0.60
	if (bccomp($max, $mmax) < 0)
		$max = bcadd($max, '0.1');
	$arr = array();
	while (bccomp($min, $max) <= 0){
		$arr[(string)$min] = 0;
		$min = bcadd($min, '0.1');
	}

return $arr;
}

$sql = "SELECT MAX(discri) AS mmax, MIN(discri) AS mmin FROM question_stats";
$res = $db->sql_query($sql);
$row = $db->sql_fetchrow($res);
$min = $row['mmin']; 
$max = $row['mmax'];
$ranges = get_ranges($min, $max);

$chart = $db->sql_query("SELECT `discri`, COUNT(`discri`) AS occurrence FROM question_stats WHERE quiz_id = '$qid' GROUP BY `discri` ORDER BY `discri`");    
while( $row = $db->sql_fetchrow($chart)) {
$base = get_base($row['discri']);
$ranges[$base] += $row['occurence'];
} print_r($ranges);

The following was my initial post seeking help.

I have been working on this chart for awhile now and have it working to a point. What I have is data from my question_stats table. One of these values is called a discriminator and I need it graphed.

Currently the graph displays number of occurrences for each discriminator value as shown in the attached pic.

I need the values grouped into ranges such as:

$discri >= -0.30 AND $discri <= -0.21
$discri >= -0.20 AND $discri <= -0.21
$discri >= -0.10 AND $discri <= -0.01
$discri >= 0 AND $discri <= .09
$discri >= 0.10 AND $discri <= 0.19
$discri >= 0.20 AND $discri <= 0.29
$discri >= 0.30 AND $discri <= 0.39

I need the number of occurrences that this values would fall within these ranges. The ranges would be my X axis and the # of occurrences my Y axis. I would also need to find the MIN(discri) to know where to start my X axis on the graph. Once I find the min I could round(discri) to get to a -0.20 or -0.10 to know which range is first on the X axis.

    How big are these numbers you're working with? Could you perhaps just replace "bcsub($r,'0.1')" with "$r-0.1" and so on?

      They are very small. A MAX(discriminator) returns something like .8

      The MIN value is like a -.6

        I'm guessing that Weedpacket was referring to significant digits rather than the numbers' magnitude. Since it seems your numbers use at most two fractional digits, I'd agree with your powers-that-be that bcmath is unnecessary; plain old php math functions should do the job well.

          No; I was speaking about magnitude, though precision is relevant as well. There might have been cause somewhere (though I didn't see it) for numbers like 4*101000 to be involved. Basically, I was wondering why the bcmath functions were being used in the first place. I get the impression that this is a third-party application: that would explain it.

          If rounding to two decimal places is required, then judicious [man]round[/man] would cover that necessity.

            2 months later

            If I wanted to replace bcomp would this work?

            if ($min == $mmin) {
            	$val = 0;
            	}
            	else if ($min > $mmin) {
            	$val = 1;
            	}else{
            	$val = -1;
            	}

              I tried to replace some of these with simple math and got the following:

              Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 87 bytes)

              My new get_base function looks like this.

              function get_base($x){
              	//divide by 10 and multiply by 10, so that
              	//we can get rid of the digit at the 0.0x position.
              	$a = ($x / 10);
              	$b = round($a, 0);	
              
              $c = ($b * 10);
              $r = round($c, 0);	
              
              //if the number is less than 0, reduce it by 0.1
              if ($x < 0) {
              	$r = ($r - 0.1);
              	}	
              
              return $r;
              }

              And then my new get_ranges looks like this.

              function get_ranges($mmin, $mmax){
              	$min = get_base($mmin);
              
              if ($min == $mmin) {
              $minval = 0;
              }
              else if ($min > $mmin) {
              $minval = 1;
              }else{
              $minval = -1;
              }	
              
              if ($minval > 0)
              	$min = ($min - 0.1);
              $max = get_base($mmax);
              // a positive number is rounded to off 0.x position.
              // if number is something like 0.51 we need 0.60 as max to
              // fit 0.51 in the range of 0.50-0.60
              if ($max == $mmax) {
              $maxval = 0;
              }
              else if ($max > $mmax) {
              $maxval = 1;
              }else{
              $maxval = -1;
              }
              
              if ($maxval < 0)
              	$max = ($max + 0.1);
              $arr = array();
              
              if ($min == $max) {
              $compval = 0;
              }
              else if ($max > $max) {
              $compval = 1;
              }else{
              $compval = -1;
              }	
              
              while ($compval <= 0){
              	$arr[(string)$min] = 0;
              	$min = ($min + 0.1);
              }
              
              return $arr;
              }
              

                You're running out of memory somewhere; somewhere you're assigning a lot of data to something and it's turning out to be too much. So ... where are you assigning arbitrary amounts of of data?

                   while ($compval <= 0){
                        $arr[(string)$min] = 0;
                        $min = ($min + 0.1);
                    }
                

                Assuming this loop ever starts, when will it end?

                  I'm starting this over since I
                  a) don't understand the original coders logic, and
                  b) from what I have been told I don't need to use bcmath.

                    Write a Reply...