Mac/Macintosh educational/tutor software developer

Faraday R&D

| Home | Source Code |

Mac Web Developer (Australia): PHP Example -- sprintf

Source code

A PHP source code example of how to use sprintf to produce smarter formatting of floating point numbers.

Motivation: displaying floating point numbers in computer-aided instruction web applications.

  • it is desirable to display simple whole numbers as simple whole numbers without a large number of zero's being appended for padding.
  • displaying a floating point number with a large number of digits can cause layout problems in a web page by overflowing the available space.

The solution is to limit the field width and that in turn may require scientific notation to represent the truncated number. The source code below shows a number of experiments: smart_format(), fixed_width_format() and fixed_digit_format() that attempt to solve this problem.

The default formatting of a floating point number produces the results shown in this article on using ini_set() and init_get() to control floating point number display precision.
 

Comments or corrections welcome. Send an email to farad'aty'farad.com.au.
 

Run smart_format test...
Run test_fixed_width_format test...
Run test_fixed_digits_format test...

<?php
/*
------------------------------------------------------------------
This code is a workaroud by radu dot rendec at ines dot ro
for bug in sprintf in which %e format specifier does not work.
From: <http://www.php.net/manual/en/function.sprintf.php>
*/
function scientific_notation($in_float_value, $in_decimal_place_count = -1) 
{
    
  // Get the exponent
  $abs_float_value = abs($in_float_value);
  $exponent = floor($abs_float_value == 0 ? 0 : log10($abs_float_value));
  // Scale to get the mantissa
  $in_float_value *= pow(10, -$exponent);
  // Create the format string based 
  // on the requested number of decimal places.
  $format = ($in_decimal_place_count >= 0) ? "." . $in_decimal_place_count : "";
  //echo("Format0: $format");
  // Format the exponent part using zero padding.
  $formatted_exponent = "+" . sprintf("%02d", $exponent);
  if($exponent < 0.0)
  {
      $formatted_exponent = "-" . sprintf("%02d", -$exponent);
  }
  $format = "%" . $format . "fe%s";
  //echo("Format1: $format");
  // Return the final value combining mantissa and exponent
  return sprintf($format, $in_float_value, $exponent);
    
}
/*
------------------------------------------------------------------
If the magnitude of the value is greater than or equal to 10.0 
or less or equal to 0.1 use normal formatting otherwise
convert to scientific notation.
*/
function smart_format($in_float_value, $in_decimal_place_count)
{
    $k_epsilon = 1e-10;
    $result = "";
    if( abs($in_float_value) < $k_epsilon)
    {
      $result = "0";
    }
    else if(abs($in_float_value) < 0.1)
    {
        $result = scientific_notation($in_float_value, $in_decimal_place_count);
    }
    else if(abs($in_float_value) >= 0.1 && abs($in_float_value) <= 10.0)
    {
        $result = (string)$in_float_value;
    }
    else
    {
        $result = scientific_notation($in_float_value, $in_decimal_place_count);
    }
    return $result;
}

/*
------------------------------------------------------------------
If the length of the number is greater than the field width
use floating point formatting for numbers greater than or equal to 0.1 
and less than 10.00 otherwise convert to scientific notation.
*/
function fixed_width_format($in_float_value, $in_field_width = 8)
{
    $k_epsilon = 1e-10;
    $result = (string)$in_float_value;
    $char_count = strlen($result);
    if($char_count <= $in_field_width)
    {
        // Do nothing;
    }
    else if( abs($in_float_value) < $k_epsilon)
    {
      $result = "0";
    }
    else if( 0.10 <= abs($in_float_value) && abs($in_float_value) < 10.00)
    {
        $decimal_place_count = $in_field_width - strlen("0.");
        $decimal_place_count += $in_float_value >= 0.0 ? 0 : -1;
        if($decimal_place_count >= 0)
        {
          $result = (string)round($in_float_value, $decimal_place_count);
        }
        else
        {
          $result = "#";
        }
    }
    else
    {
        $decimal_place_count = $in_field_width - strlen("0.e+00");
        $decimal_place_count += $in_float_value >= 0.0 ? 0 : -1;
        if($decimal_place_count >= 0)
        {
          $result = scientific_notation($in_float_value, $decimal_place_count);
        }
        else
        {
          $result = "#";
        }
    }
    return $result;
}

/*
------------------------------------------------------------------
If the length of the number is greater than the field width
use floating point formatting for numbers greater than or equal to 0.1 
and less than 10.00 otherwise convert to scientific notation.
The number of decimal digits used in the mantissa of the 
floating point number is the same as the field width.
The number of digits displayed is not adjusted for the sign.
*/
function fixed_digits_format($in_float_value, $in_digits_count = 8)
{
    $k_epsilon = 1e-10;
    $result = (string)$in_float_value;
    $char_count = strlen($result);
    if($char_count <= $in_field_width)
    {
      // Do nothing;
    }
    else if( abs($in_float_value) < $k_epsilon)
    {
      $result = "0";
    }
    else if( 0.10 <= abs($in_float_value) && abs($in_float_value) < 10.00)
    {
      $decimal_place_count = $in_digits_count - strlen("0");
      if($decimal_place_count >= 0)
      {
        $result = (string)round($in_float_value, $decimal_place_count);
      }
      else
      {
        $result = "#";
      }
    }
    else
    {
      $decimal_place_count = $in_digits_count - strlen("0");
      if($decimal_place_count >= 0)
      {
        $result = scientific_notation($in_float_value, $decimal_place_count);;
      }
      else
      {
        $result = "#";
      }
    }
    return $result;
}

/*
------------------------------------------------------------------
The test procedure.
Test 10 times.
*/
function test($in_float_value,  $in_decimal_place_count = -1)
{
    $result = "";
    $float_value = $in_float_value;
    $count = 20;
    for($index = 0; $index < $count; $index++)
    {
        $result = smart_format($float_value, 5);
        //$result = (string)($float_value);
        //$result = scientific_notation($float_value, $in_decimal_place_count);
        echo("$index: $float_value ---> $result<BR>\n");
        $float_value = $float_value * 10.0;
    }
    echo("<BR>\n");
    echo(" \n");
    echo("<BR>\n");
    $float_value = $in_float_value;
    for($index = 0; $index < $count; $index++)
    {
        $result = smart_format($float_value, 5);
        //$result = (string)($float_value);
        //$result = scientific_notation($float_value, $in_decimal_place_count);
        echo("$index: $float_value ---> $result<BR>\n");
        $float_value = $float_value / 10.0;
    }
}
?>
Run smart_format test...
Run test_fixed_width_format test...
Run test_fixed_digits_format test...
| Copyright © 2004, Faraday R&D. | Feedback |