Skip to page content or skip to Accesskey List.
Search evolt.org
evolt.org login: or register

Work

Main Page Content

Working With Fractions In CSS and PHP

Rated 4.07 (Ratings: 1) (Add your rating)

Log in to add a comment
(6 comments so far)

Want more?

  • More articles in Code
  • More articles by bpeh
 
Picture of bpeh

Bernard Peh

Member info | Full bio

User since: October 15, 2006

Last login: October 04, 2007

Articles written: 2

Most of us are uncomfortable with using fractions when writting programs. If we encounter a fraction, we will first convert it into a floating point number (with decimals) and proceed from there. Most programming languages would prefer to use 0.5 as opposed to 1/2 because the later might conflict with the syntax of the languages. In this article, I will discuss my attempt to work with fractions in one of the PHP projects that I have done.

Displaying Fractions In HTML

There are a few ways to display fractions in the web. The most common way is just to add a slash between 2 numbers, like so "1/2". There are also special HTML characters that we can make fractions look more professional. Eg. to display 1/2, we can use the HTML code ½. However, not many fractions are supported by HTML. So, you may be in trouble if you want to display 2/9 in HTML.

A better way to display a fraction is probably to use the superscript and subscript tags. Using <sup> and <sub> tags, my 2/9 will look a bit better. We can also use a "special slash" &#8260; between 2 numbers instead of a normal slash ( / ). Still not satisfied? With CSS, we can push the limit further.

If we define a css like this:

  .fracNum, .fracDen {
         font-size: 70%;
  }
  .fracNum { vertical-align: 0.5em; }
  .fracDen { vertical-align: -0.5em; }

and when implemented with the 'sup' and 'sub' tags, The fraction will look even better. The code will be something like:

  <sup class="fracNum">2</sup>&#8260;<sub class="fracDen">9</sub>

Converting Decimals To Fraction - A Real Example

I wrote a program that let people frame their pictures online. When I was halfway through, I was told that the program should support imperial measurements (inches). The problem with working in inches is that very few people would say my picture is 6.34 inch width by 9.82 inch height; Most people would say 6 and 3/8 inch by 9 and 3/8 height for example.

The biggest problem now is that the framing engine calculates everything in mm. Instead of rewritting the whole engine, I figured out that what I need is just an interface to convert mm to inches. So, if I pass 300mm into a function, it should return me 11 and 3/4 as the answer. Dividing 300mm by 1 inch (25.4mm) will leave me with a long decimal. It would be silly to try and display a fraction for a decimal like 0.1111. The function should be intelligent enough to round off the decimal to something that can be easily displayed as a fraction. For example, if I round off 0.1111 to 0.125, I can display the fraction as 1/8 instead of 1111/100000. Time is running short and I need a simple and sweet solution.

Implementation

I would like to go through snipplets of code with explaination first before revealing everything. Feel free to jump to the end of the page and copy the whole function if you just want to implement it in your website. The code is written in PHP.

Part 1: Extracting the decimal in inches.

<?php
  define
(INCH_TO_MM, 25.4);
  
// 1 inch equals to 25.4mm
  
$inch = $mm / INCH_TO_MM;
  
$pWhole = explode('.',$inch);
  
$pWhole = $pWhole[0];
  
$pDecimal = $val-$pWhole;
?>

The measurement in mm is first converted to inches(with decimal). The decimal is then isolated from the whole number and stored in a var called $pDecimal. Now, I need to store a list of all possible fractions with their mm equivalent in an array. I use intervals of 1/8 for the sake of simplicity.

Part 2: Rounding off to the closest inch interval.

<?php
  $fractionOption
= array();
  
$fractionOption['0/8’] = 0;
  $fractionOption['
1/8’] = 0.125;
  
$fractionOption['1/4’] = 0.25;
  $fractionOption['
3/8’] = 0.375;
  
$fractionOption['1/2’] = 0.5;
  $fractionOption['
5/8’] = 0.625;
  
$fractionOption['3/4’] = 0.75;
  $fractionOption['
7/8’] = 0.875;
  
$fractionOption['8/8’] = 1;
  
  foreach ($fractionOption as $k => $v) {
         // Converted $pDecimal back to mm to perform calculation
         $tmpV[$k] = abs($pDecimal - $v);
  }
  
  asort($tmpV,SORT_NUMERIC);
  
  list($inch, $mm) = each($tmpV);
?>

This is the most important step in the whole conversion process. The foreach loop creates a new array called $tmpV which stores the inch fraction as the key and the inch difference as the value. We will now sort $tmpV with the minimum 'mm' value at the top and the maximum 'mm' value at the bottom using the asort function. We are extracting the first entry in the array because it stores the minimum 'mm' difference. As you can see, what we are trying to do here is to round $pDecimal off to the closest decimal value in the $fractionOption array (ie, 0.125, 0.25, 0.375..etc).

We can now safely extract the first key-value pair in $tmpV using the list function. The $inch var stores the inch representation that we want.

Part 3: Cleaning Up

<?php
  $inch
= ($inch == '0/8') ? '': $inch;
  
// round off to nearest whole number if 8/8
  
if ($inch == '8/8') {
      
$inch = '';
      
$pWhole++;
  }
?>

We do not want to display the fraction if it is ‘0/8’ or ‘8/8’ because it is pretty much meaningless. However, if the fraction is ‘8/8’, we have to increase the whole number by 1.

Part 4: Adding some CSS

<?php
  
if ($inch != '') {
      
$tFrac = explode('/',$inch);
      
// again please replace [] with the real html tags
      
$fraction = "[sup class='fracNum']$tFrac[0][/sup]&#8260;[sub class='fracDen']$tFrac[1][/sub]";
  }
  else {
      
$fraction = '';
  }
  return
"$pWhole $fraction";
?>

Remember that we eliminated any fractions that are '0/8' or '8/8'? So we only need to process any fraction that falls within the range of '1/8' to '7/8'. By splitting the fractions into numerators and denominators, we can now apply our CSS technique mentioned above.

The Whole Thing

As promised, the full code is displayed below:

<?php
function mmToInch ($val) {

       
$fractionOption = array();
       
$fractionOption['0/8'] = 0;
       
$fractionOption['1/8'] = 0.125;
       
$fractionOption['1/4'] = 0.25;
       
$fractionOption['3/8'] = 0.375;
       
$fractionOption['1/2'] = 0.5;
       
$fractionOption['5/8'] = 0.625;
       
$fractionOption['3/4'] = 0.75;
       
$fractionOption['7/8'] = 0.875;
       
$fractionOption['8/8'] = 1;
       
define(INCH_TO_MM, 25.4);

       
$val = $val/INCH_TO_MM;
       
$pWhole = explode('.',$val);
       
$pWhole = $pWhole[0];
       
$pDecimal = $val-$pWhole;
              
       foreach (
$fractionOption as $k => $v) {
              
$tmpV[$k] = abs($pDecimal - $v);
       }
       
       
asort($tmpV,SORT_NUMERIC);
       list(
$inch, $mm) = each($tmpV);

       
// nullify pWhole and pFraction
       
$pWhole = ($pWhole == 0) ? '': $pWhole;
       
$inch = ($inch == '0/8') ? '': $inch;


       
// round off to nearest whole number if 8/8
       
if ($inch == '8/8') {
              
$inch = '';
              
$pWhole++;
       }
       
       
// strip inch and return fraction formatted in css
      
if ($inch != '') {
             
$tFrac = explode('/',$inch);
              
$fraction = "<sup class='fracNum'>$tFrac[0]</sup>&#8260;<sub class='fracDen'>$tFrac[1]</sub>";
       }
       else {
              
$fraction = '';
       }
       return
$pWhole.' '.$fraction;   
}

// testing
echo "67.885 mm is equivalent to ".mmToInch(66.885)." inches";
?>

The sourcecode can be dowloaded at http://web-developer.sitecritic.net/mmToInch_function.txt

Conclusion

I hope that the decimal to fraction conversion solution shown in this tutorial is straight forward and easy to implement. The script rounds off any decimal value to the closest one-eighth of an inch. If you want more accuracy, you can make your fraction interval smaller, for example 1/16 or 1/32...and so on. The logic used in this example can be easily applied to other programming languages. Feel free to try the online framing program at http://www.clubframeco.com/smartFramer.html. Make sure you select the inch option to see fractions in action.

Bernard Peh specialises mainly in SEO and PHP programming. He is also the web developer behind Sitecritic.net Web Design. During his free time, he maintains his melbourne web developer blog.

Unicode!

Submitted by ijoshua on February 12, 2007 - 16:17.

This is sort of a silly “solution,” considering that if your page encoding is properly set for UTF-8, you get typographical fractions for free in the unicode table around U+00b0 and U+2150. Let’s see if I can manage to get these through in the comment form.

fractionsymbolUnicode
0.125U+215b
0.167U+2159
0.25¼U+00bc
0.333U+2153
0.375U+215c
0.5½U+00bd
0.625U+215d
0.667U+2154
0.75¾U+00be
0.8335U+215a
0.875U+215e

login or register to post comments

Still, your PHP code could

Submitted by ijoshua on February 12, 2007 - 16:29.

Still, your PHP code could be repurposed to make use of these Unicode symbols. The extra formatting and CSS become unnecessary, and you would cut several bytes from the weight of each page [2 bytes for a Unicode symbol vs. 63 for your marked-up version.]

login or register to post comments

Speed boost

Submitted by dachande663 on February 13, 2007 - 14:44.

I know it's only a small thing, but couldn't you just floor the floating point value to get the integer value rather than having to explode it?

login or register to post comments

RE: Unicode @ijoshua

Submitted by nettles on April 20, 2007 - 19:55.

That's a very good idea, but, if you are really concerned about appearance, you will notice that the fractions are rendered differently in some browsers. The quarter, half and three-quarter fractions appear bolder in many fonts, relative to the lighter anti-aliasing of the other fractions.

Additionally, as mentioned, I don't know of a way to get 13/200 accomplished in Unicode, so if your goal is to represent scientific data, then perhaps you'd be in good shape with this solution.

An advantage to the stock Unicode entities is that screen readers and other non-visual tools will (hopefully) recognize the Unicode entity and pronounce it as "three fourths" as opposed to "3 slash 4" in the case of the suggested alternative.

So I guess the net is, whichever meets your needs best :)

login or register to post comments

Excellent article

Submitted by Tjeerd Kramer on May 7, 2007 - 15:17.

Excellent article, just what I needed!

login or register to post comments

That's a very good idea,

Submitted by TMaxim on October 20, 2007 - 14:40.

That's a very good idea, but, if you are really concerned about appearance, you will notice that the fractions are rendered differently in some browsers. The quarter, half and three-quarter fractions appear bolder in many fonts, relative to the lighter anti-aliasing of the other fractions.

Max

login or register to post comments

The access keys for this page are: ALT (Control on a Mac) plus:

evolt.orgEvolt.org is an all-volunteer resource for web developers made up of a discussion list, a browser archive, and member-submitted articles. This article is the property of its author, please do not redistribute or use elsewhere without checking with the author.