Skip to main content

OverpunchFormat - Java class


OverpunchFormat is a subclass of DecimalFormat that formats decimal numbers into NSF Overpunch Format.


The purpose of an Overpunch format is to encode the sign (+/-) into the least significant (right-most) digit via an encoding scheme. Also the values are typically dollar amounts, and therefore are integers representing cents (1/100 dollar). The use of DecimalFormat's setMultipler method will make quick work of this scaling.

Get the Java source code for OverpunchFormat.java.

OverpunchFormat is a subclass of DecimalFormat that formats decimal numbers into NSF Overpunch Format.

The purpose of an Overpunch format is to encode the sign (+/-) into the least significant (right-most) digit via an encoding scheme. Also the values are typically dollar amounts, and therefore are integers representing cents (1/100 dollar). The use of DecimalFormat's setMultipler method will make quick work of this scaling.


//package name.koontz.util;

import java.io.Serializable;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.text.FieldPosition;
//import java.lang.Number;
//import java.lang.StringBuffer;
import java.text.*;


/**
* OverpunchFormat is a subclass of DecimalFormat that formats
* decimal numbers into NSF Overpunch Format.
*
* The purpose of an Overpunch format is to encode the sign (+/-) into the
* least significant (right-most) digit via an encoding scheme.  Also the values are
* typically dollar amounts, and therefore are integers representing cents
* (1/100 dollar). The use of the setMultipler method will make quick work of
* this scaling.
*
*

*
* Holy hanging chad! Batman, the bat computer has detected an
* overpunched field, what could it mean?
*
* Well, Robin, it means the Joker has saved a byte in transmition cost, but it
* will take the bat computer only 23 instructions to figure out what this sign
* could be...
*

*

*
*
* OverpunchFormat does not support locales, itself!  So do not expect Kanji
* characters in your overpunched output.
*
*
*

Overpunch Encoding

*


*             Least
*          Significant   Positive      Negative
*             Digit     Overpunch     Overpunch
*               0           {             }
*               1           A             J
*               2           B             K
*               3           C             L
*               4           D             M
*               5           E             N
*               6           F             O
*               7           G             P
*               8           H             Q
*               9           J             R
*
*

*
* Example:
*

* -1575  =>  157N
* +1200  =>  120{
*

*
*
* If OverpunchFormat.parse(String, ParsePosition) fails to parse a string, it
* returns null, leaves the ParsePosition index unchanged, and sets the
* ParsePosition error index.
*
* A OverpunchFormat pattern contains only a postive pattern (no negative subpattern).
* Since the whole concept of an overpunched value is to
* encode the sign within the last digit, there will be no negative subpattern.
*
*
* Note:  DecimalFormat JVM 1.2.2 bugs Sun Bug Id 4322804, 4254220, 4243108
*
*
* @see Format
* @see NumberFormat
* @see DecimalFormat
* @see ParsePosition
*/
public class OverpunchFormat extends java.text.DecimalFormat
    implements Cloneable, Serializable  {

    // array of overpunch replacement characters
    private static final char[] positiveDigit = {'{', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I'};
    //                          overpunch digit   0    1    2    3    4    5    6    7    8    9
    private static final char[] negativeDigit = {'}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R'};


    public OverpunchFormat() {
        super();
    }

    public OverpunchFormat(String pattern) throws IllegalArgumentException  {
        super(pattern);
        //
    }

    /**
     * Returns an instance of Number with a value matching the given string.
     *
     *
     * @param text                the string to be parsed
     * @param parsePosition       on entry, where to begin parsing; on exit, just past the last parsed character. If parsing fails, the index will not move and the error index will be set.
     * @return                    the parsed value, or null if the parse fails
     */
    public Number parse(String text, ParsePosition parsePosition) {
        //
        int sign = 1;  // or -1 if negative
        char lastDigit;
        char overpunchChar = '{';
        int overpunchIndex = 0;

        // start at the parsePosition within text - look for a non-numeric char
        // that's the overpunch char
        if ( parsePosition.getIndex() < text.length() ) {
            for (int i = parsePosition.getIndex(); i < text.length(); i++) {
                char c = text.charAt(i);
                if ( Character.getType(c) == Character.DECIMAL_DIGIT_NUMBER ) {
                    continue;
                } else {
                    // found first non digit char - that's the overpunch
                    overpunchChar = c;
                    overpunchIndex = i;
                    break;
                }
            }
        }

        // reverse the overpunch

        switch (overpunchChar) {
        case  '}':
             sign = -1;
             lastDigit = '0';
             break;
        case  '{':
             sign = 1;
             lastDigit = '0';
             break;
        case  'A':
             sign = 1;
             lastDigit = '1';
             break;
        case  'B':
             sign = 1;
             lastDigit = '2';
             break;
        case  'C':
             sign = 1;
             lastDigit = '3';
             break;
        case  'D':
             sign = 1;
             lastDigit = '4';
             break;
        case  'E':
             sign = 1;
             lastDigit = '5';
             break;
        case  'F':
             sign = 1;
             lastDigit = '6';
             break;
        case  'G':
             sign = 1;
             lastDigit = '7';
             break;
        case  'H':
             sign = 1;
             lastDigit = '8';
             break;
        case  'I':
             sign = 1;
             lastDigit = '9';
             break;
        case  'J':
             sign = -1;
             lastDigit = '1';
             break;
        case  'K':
             sign = -1;
             lastDigit = '2';
             break;
        case  'L':
             sign = -1;
             lastDigit = '3';
             break;
        case  'M':
             sign = -1;
             lastDigit = '4';
             break;
        case  'N':
             sign = -1;
             lastDigit = '5';
             break;
        case  'O':
             sign = -1;
             lastDigit = '6';
             break;
        case  'P':
             sign = -1;
             lastDigit = '7';
             break;
        case  'Q':
             sign = -1;
             lastDigit = '8';
             break;
        case  'R':
             sign = -1;
             lastDigit = '9';
             break;
        default:
             // not the overpunch char - error
             parsePosition.setErrorIndex(overpunchIndex);
             return null;  // error return null

        }

        // replace with the overpunch char in text with the digit
        StringBuffer sb = new StringBuffer(text);

        sb.setCharAt(overpunchIndex, lastDigit);

        // now call the super's function
        Number n = super.parse(sb.toString(), parsePosition);

        if ( n instanceof Double ) {
            double d = n.doubleValue();
            d = d * sign;
            n = new Double(d);
        } else if ( n instanceof Long ) {
            long l = n.longValue();
            l = l * sign;
            n = new Long(l);
        } else {
            ;  // nothing
        }

        return n;
    }

    /**
     * Formats a long to produce a string.
     *
     * @param number               the long to format
     * @param result               where the text is to be appended
     * @param fieldPosition        On input: an alignment field, if desired. On output: the offsets of the alignment field.
     * @return                     The value passed in as the result parameter
     */
    public StringBuffer format(long number, StringBuffer result, FieldPosition fieldPosition) {
//System.out.println("OverpunchFormat.format|long number");
//System.out.println("OverpunchFormat.format( "+number+", "+result.toString()+", "+fieldPosition+" )");
        //
        StringBuffer buf = new StringBuffer(result.length()+20);
        long abs = Math.abs(number);          // get the absolute value
//System.out.println("    abs = "+abs);

        // call DecmialFormat to format all but the overpunch
        buf = super.format(abs, result, fieldPosition);
//System.out.println("    super.format() returns buf = " + buf.toString());
        // now we must workout the overpunch
        //
        // get last digit of the string
        char overpunchChar = buf.charAt(buf.length()-1);
//System.out.println("    buf.length()-1 = " + (buf.length()-1));
//System.out.println("    overpunchChar = " + overpunchChar);
        // convert last digit to index into the overpunch (+/-) array
        int overpunchIndex = Character.getNumericValue(overpunchChar);
//System.out.println("    overpunchIndex = " + overpunchIndex);
        // get overpunch char
        if ( number < 0 ) {
            overpunchChar = negativeDigit[overpunchIndex];
        } else {
            overpunchChar = positiveDigit[overpunchIndex];
        }
//System.out.println("    overpunchChar = " + overpunchChar);
        // replace the lastChar in the string with new lastChar
        buf.deleteCharAt(buf.length()-1);
        buf.append(overpunchChar);
//System.out.println("    buf = " + buf.toString());

        return buf;
    }

    /**
     * Formats a double to produce a string.
     *
     * @param number               the double to format
     * @param result               where the text is to be appended
     * @param fieldPosition        On input: an alignment field, if desired. On output: the offsets of the alignment field.
     * @return                     The value passed in as the result parameter
     */
    public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
//System.out.println("OverpunchFormat.format|double number");
//System.out.println("OverpunchFormat.format( "+number+", "+result.toString()+", "+fieldPosition+" )");
        //
        StringBuffer buf = new StringBuffer(result.length()+20);
        double abs = Math.abs(number);          // get the absolute value
//System.out.println("    abs = "+abs);

        // call DecmialFormat to format all but the overpunch
        buf = super.format(abs, result, fieldPosition);
//System.out.println("    super.format() returns buf = " + buf.toString());

        // now we must workout the overpunch
        //
        // get last digit of the string
        char overpunchChar = buf.charAt(buf.length()-1);
//System.out.println("    buf.length()-1 = " + (buf.length()-1));
//System.out.println("    overpunchChar = " + overpunchChar);

        // convert last digit to index into the overpunch (+/-) array
        int overpunchIndex = Character.getNumericValue(overpunchChar);
//System.out.println("    overpunchIndex = " + overpunchIndex);

        // get overpunch char
        if ( number < 0 ) {
            overpunchChar = negativeDigit[overpunchIndex];
        } else {
            overpunchChar = positiveDigit[overpunchIndex];
        }
//System.out.println("    overpunchChar = " + overpunchChar);

        // replace the lastChar in the string with new lastChar
        buf.deleteCharAt(buf.length()-1);
        buf.append(overpunchChar);
//System.out.println("    buf = " + buf.toString());


        return buf;
    }



    /**
     *  The main program for the class - a test method.
     *
     *@param  args  the text to parse
     */
    public static void main(String[] args) {

        OverpunchFormat of = new OverpunchFormat();
        of.applyPattern("0000000"); // fixed field zero padded
        of.setMultiplier(100);      // imply 2 decimal places

        if (args.length < 2) {
            System.out.println("Usage: java OverpunchFormat 'pattern' 'value'");
            System.out.println("Examples format():");
            System.out.println("  9876      -> " +of.format(9876l));
            System.out.println("    -1.35   -> " +of.format(-1.35));
            System.out.println("      .2389 -> " +of.format(0.2389));
            System.out.println("note; fixed field zero padding, implied decimal place, rounding and encoding");

            StringBuffer sb = new StringBuffer("x=012345F dollars ");
            ParsePosition pos = new ParsePosition(2);
            System.out.println("Examples parse():");
            System.out.println("  before call:" + sb);
            System.out.println("  parse(sb, pos) where pos =" + pos);
            System.out.println("  parse returns a Number = " + of.parse(sb.toString(), pos));
            System.out.println("  and sets ParsePosition.index = " + pos.getIndex() + " & errorIndex = " + pos.getErrorIndex());


            System.exit(99);
        } else {
            StringBuffer sb = new StringBuffer("OverpunchFormat of "+ args[1] +" is ");
            of.applyPattern(args[0]);
            of.format(Double.valueOf(args[1]), sb, new FieldPosition(NumberFormat.FRACTION_FIELD) );

            System.out.println(sb.toString());

        }

    }


}


Post a Comment

Most Popular on Agile Complexification Inverter

David's notes on "Drive"

- "The Surprising Truth about what Motivates Us" by Dan Pink.

Amazon book order
What I notice first and really like is the subtle implication in the shadow of the "i" in Drive is a person taking one step in a running motion.  This brings to mind the old saying - "there is no I in TEAM".  There is however a ME in TEAM, and there is an I in DRIVE.  And when one talks about motivating a team or an individual - it all starts with - what's in it for me.

Introduction

Pink starts with an early experiment with monkeys on problem solving.  Seems the monkeys were much better problem solver's than the scientist thought they should be.  This 1949 experiment is explained as the early understanding of motivation.  At the time there were two main drivers of motivation:  biological & external influences.  Harry F. Harlow defines the third drive in a novel theory:  "The performance of the task provided intrinsic reward" (p 3).  This is Dan Pink's M…

What is your Engagement Model?

What must an Agile Transformation initiative have to be reasonably assured of success?

We "change agents" or Agilist, or Organizational Development peeps, or Trouble Makers, or Agile Coaches have been at this for nearly two decades now... one would think we have some idea of the prerequisites for one of these Transformations to actually occur.  Wonder if eight Agile Coaches in a group could come up with ONE list of necessary and sufficient conditions - an interesting experiment.  Will that list contain an "engagement model"?  I venture to assert that it will not.  When asked very few Agile Coaches, thought leaders, and change agents mention much about employee engagement in their plans, models, and "frameworks".  Stop and ask yourselves ... why?

Now good Organizational Development peeps know this is crucial, so I purposely omitted them from that list to query.

One, central very important aspect of your Agile Transformation will be your Engagement model.  

Exercise:: Definition of Ready & Done

Assuming you are on a Scrum/Agile software development team, then one of the first 'working agreements' you have created with your team is a 'Definition of Done' - right?



Oh - you don't have a definition of what aspects a user story that is done will exhibit. Well then, you need to create a list of attributes of a done story. One way to do this would be to Google 'definition of done' ... here let me do that for you: http://tinyurl.com/3br9o6n. Then you could just use someone else's definition - there DONE!

But that would be cheating -- right? It is not the artifact - the list of done criteria, that is important for your team - it is the act of doing it for themselves, it is that shared understanding of having a debate over some of the gray areas that create a true working agreement. If some of the team believes that a story being done means that there can be no bugs found in the code - but some believe that there can be some minor issues - well, …

Refactoring - examples from the book

Martin Fowler's book Refactoring:  Improving the Design of Existing Code has a simple example of a movie rental domain model, which he refactors from a less than ideal object-oriented design to a more robust OO design. Included in this Refactoring_FirstExample.zip Zip file are the Java source code files of the Movie, Rental, and Customer classes. Along with a JUnit CustomerTest class. Using these example source files you too can follow along with the refactoring that Fowler presents in the first few chapters of his book.


Metrics for a Scrum Team (examples)

What metrics do you collect to analyze your scrum team?

We live in a world of data and information.  Some people have a mindset that numbers will diagnose all problems – “just show me the data.”  Therefore many directors and senior managers wish to see some list of metrics that should indicate the productivity and efficiency of the Scrum team.  I personally believe this is something that can be felt, that human intuition is much better in this decision realm than the data that can be collected.  However, one would have to actually spend time and carefully observe the team in action to get this powerful connection to the energy in a high-performing team space.  Few leaders are willing to take this time, they delegate this information synthesis task to managers via the typical report/dashboard request.  Therefore we are asked to collect data, to condense this data into information, all while ignoring the intangible obvious signals (read Honest Signals by Sandy Pentland of MIT).
What if …