The Lab Book Pages

An online collection of electronics information

http://www.labbookpages.co.uk

Dr. Andrew Greensted
Last modified: 12th January 2015

Hide Menu


Valid XHTML Valid CSS
Valid RSS VIM Powered
RSS Feed Icon

This site uses Google Analytics to track visits. Privacy Statement

Page Icon
Download

Download Files
EngNotation.java

Engineering Notation in Java

This simple pair of java functions can be used for converting between a double value and a string formatted in engineering notation.


Double to a String

The function below takes a double value and returns a string formatted in engineering notation. The number of digits after the decimal point is specified by the dp argument. Some examples are listed below.

val dp Output
0.01 2 10.00m
12456 1 12.5k
56000000 0 56M
0.0006819 3 681.900μ
private final static int PREFIX_OFFSET = 5;
private final static String[] PREFIX_ARRAY = {"f", "p", "n", "µ", "m", "", "k", "M", "G", "T"};

public static String convert(double val, int dp)
{
   // If the value is zero, then simply return 0 with the correct number of dp
   if (val == 0) return String.format("%." + dp + "f", 0.0);

   // If the value is negative, make it positive so the log10 works
   double posVal = (val<0) ? -val : val;
   double log10 = Math.log10(posVal);

   // Determine how many orders of 3 magnitudes the value is
   int count = (int) Math.floor(log10/3);

   // Calculate the index of the prefix symbol
   int index = count + PREFIX_OFFSET;

   // Scale the value into the range 1<=val<1000
   val /= Math.pow(10, count * 3);

   if (index >= 0 && index < PREFIX_ARRAY.length)
   {
      // If a prefix exists use it to create the correct string
      return String.format("%." + dp + "f%s", val, PREFIX_ARRAY[index]);
   }
   else
   {
      // If no prefix exists just make a string of the form 000e000
      return String.format("%." + dp + "fe%d", val, count * 3);
   }
}

String to Double

The two functions listed below can be used to take a String or a char array containing a number in engineering notation and parse them into a double value. On error a NumberFormatException is thrown. The functions will ignore white space characters before and after the encoded number. Some examples are listed in the table below.

String Output
1.4k 1400.0
245m7 0.2457
12.56M 12560000.0
private final static char[] PREFIX_TEST_ARRAY = {'f', 'p', 'n', 'u', 'µ', 'm', 'k', 'K', 'M', 'G', 'T'};
private final static int[] PREFIX_EXP_ARRAY = {-15, -12, -9, -6, -6, -3, 3, 3, 6, 9, 12};

public static double parse(String str)
{
   return parse(str.toCharArray());
}

public static double parse(char[] chars) throws NumberFormatException
{
   int exponent = 0;
   double value = 0;

   boolean gotChar = false;      // Set to true once any non-whitespace, or minus character has been found
   boolean gotMinus = false;     // Set to true once a minus character has been found
   boolean gotDP = false;        // Set to true once a decimal place character has been found
   boolean gotPrefix = false;    // Set to true once a prefix character has been found
   boolean gotDigit = false;     // Set to true once a digit character has been found

   // Search for start of string
   int start = 0;
   while (start < chars.length) {
      if (chars[start] != ' ' && chars[start] != '\t') break;
      start ++;
   }

   if (start == chars.length) throw new NumberFormatException("Empty string");

   // Search for end of string
   int end = chars.length - 1;
   while (end >= 0) {
      if (chars[end] != ' ' && chars[end] != '\t') break;
      end --;
   }

   // Iterate through characters
   CharLoop: for (int c=start ; c<=end ; c++)
   {
      // Check for a minus symbol
      if (chars[c] == '-')
      {
         if (gotChar) throw new NumberFormatException("Can only have minus symbol at the start");
         if (gotMinus) throw new NumberFormatException("Too many minus symbols");
         gotMinus = true;
         continue CharLoop;
      }

      gotChar = true;

      // Check for a numerical digit
      if (chars[c] >= '0' && chars[c] <= '9')
      {
         if (gotPrefix || gotDP) exponent --;
         if (gotPrefix && gotDP) throw new NumberFormatException("Cannot have digits after prefix when number includes decimal point");
         value *= 10;
         value += chars[c] - '0';
         gotDigit = true;
         continue CharLoop;
      }

      // Check for a decimal place
      if (chars[c] == '.')
      {
         if (gotDP) throw new NumberFormatException("Too many decimal points");
         if (gotPrefix) throw new NumberFormatException("Cannot have decimal point after prefix");
         gotDP = true;
         continue CharLoop;
      }

      // Check for a match with a prefix character
      for (int p=0 ; p<PREFIX_TEST_ARRAY.length ; p++)
      {
         if (PREFIX_TEST_ARRAY[p] == chars[c])
         {
            if (gotPrefix) throw new NumberFormatException("Too many prefixes");
            exponent += PREFIX_EXP_ARRAY[p];
            gotPrefix = true;
            continue CharLoop;
         }
      }

      // All other characters are invalid
      throw new NumberFormatException("Invalid character '" + chars[c] + "'");
   }

   // Check if any digits were found
   if (!gotDigit) throw new NumberFormatException("No digits");

   // Apply negation if required
   if (gotMinus) value *= -1;

   return value * Math.pow(10, exponent);
}

Page Revisions

Rev NumberDateDetails
1.121/1/2015Corrected Heading.
Book Logo