Chitika

Monday, January 31, 2005

double vs. BigDecimal

Apart of continuous education and code reviews, there are still some Java codes I've found among my colleagues which are created without giving much thought on the floating-point arithmetic in Java. This is contradictory to the fact that a consistent floating-point arithmetic is essential for any financial applications.

Try and run the following code snippet:


public static void main (String[] args) {
    System.out.println (
        "(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1) = " +
        (0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1));

    double d = 0.0;
    while (d <= 1.0) d += 0.1;
    System.out.println ("d = " + d);

    System.out.println ("0.0175 * 100000 = " + 0.0175 * 100000);
}

and guess, what's the output?
You might've guessed that 1.0, 1.0, 1750.0 are the outputs, right?
Well, the results are..

(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1) = 0.9999999999999999
d = 1.0999999999999999
0.0175 * 100000 = 1750.0000000000002

So, what's the conclusion here?
1. Do not use double/float for floating-point arithmetic in Java, use BigDecimal instead. This is because Java cannot represent floating-point precisely.
2. Do not use == or != as a floating-point comparison. Compare Float.floatToIntBits (float) or Double.doubleToLongBits (double) instead. If == or != is used on float/double, there's a possibility that the code will go into infinite loop.
3. Always use BigDecimal for temporary variables, which will be processed/involved in future calculations. Convert the values to float/double only if you want to persist them into the database.

Here's an example of the code to add using BigDecimal:

// default to read a double primitive value of 18 digit
// precision
public static final NumberFormat DEFAULT_DECIMAL_FORMAT =
    new DecimalFormat ("#.0#################");
public static final BigDecimal ZERO = new BigDecimal ("0");

public static BigDecimal add (double a, double b) {
    String s = DEFAULT_DECIMAL_FORMAT.format(a);
    BigDecimal bd = new BigDecimal (s);
    return add (bd, b);
}

public static BigDecimal add (BigDecimal a, double b) {
    String s = DEFAULT_DECIMAL_FORMAT.format(b);
    BigDecimal bd = new BigDecimal (s);
    return add (a, bd);
}

public static BigDecimal add (BigDecimal a, BigDecimal b) {
    if (a == null) return (b == null) ? ZERO : b;
    return a.add (b);
}

Applying the code above, we'll have the following code:

System.out.println (
    "add (add (add (add (add (add (add (add (add (0.1, 0.1), 0.1), 0.1), 0.1), 0.1), 0.1), 0.1), 0.1), 0.1) = " +
    add (add (add (add (add (add (add (add (add (0.1, 0.1), 0.1), 0.1), 0.1), 0.1), 0.1), 0.1), 0.1), 0.1));
System.out.println (
    "new BigDecimal (\"0.0175\").multiply (new BigDecimal (\"100000\").doubleValue()) = " +
    new BigDecimal ("0.0175").multiply (new BigDecimal ("100000")).doubleValue());

And the results are..

add (add (add (add (add (add (add (add (add (0.1, 0.1), 0.1), 0.1), 0.1), 0.1), 0.1), 0.1), 0.1), 0.1) = 1.0
new BigDecimal ("0.0175").multiply (new BigDecimal ("100000").doubleValue()) = 1750.0

A note about BigDecimal is don't use the double constructor, instead use the String constructor. There is no point in trying to do the right thing if you're giving it the bad/wrong seed.. :D

Further Reading:
Effective Java Programming Language Guide

Wednesday, January 12, 2005

analyzing the Requirement Gathering process

When I tried to analyze what's the best suited way for our company to perform the Requirement Gathering process, I've come across to the following resources:
- Wikipedia on Requirement Gathering
- Requirement Analysis, an article by Karanjeet Bali

Both resources have helped me a lot in performing with the definition of the Requirement Gathering process, the challenge of effective Requirement Gathering process, and how to improve on them. Specifically, the article by Karanjeet Bali has helped me to identify many quality dimensions which can be selected as the criterias for most commonly found projects.

A few points which have caught my attention:
- Most of the people conducting the Requirement Gathering process do not always have the required knowledge to understand the business process properly.
- Not all of the requirement documents I've seen have all of the following characteristics (which are considered "must-have"): clear, complete, correct, not ambiguous, testable, traceable, prioritized, and not vague.
- Not all of the requirements which have been signed off early in the project are being tracked properly throughout the project lifetime, thus any changes in functionality, scope and priority cannot be tracked.
- Since cost and time are two properties of a project agreement which are very hard to negotiate, hence only by setting priorities on each functionality/feature of the system based on user's requirements we can negotiate better whenever there's any change in the requirement itself (either its functionality, scope, and/or priority).

One of the hardest part of the process improvement is finding a way to leverage the knowledge base of our Requirement Gathering team. Since we handled many projects from many industries, it'd be hard for us to always be prepared prior to the Requirement Gathering process.

In the mean time, I'm trying to find myself some time to read Alistair Cockburn's publications, mostly related to effectively written use cases.

Further Reading:
Writing Effective Use Cases
Managing Software Requirements: A Use Case Approach, Second Edition
Agile Software Development
Crystal Clear : A Human-Powered Methodology for Small Teams

Wednesday, January 05, 2005

Goals for Year 2005

I'm currently trying to define a workplan for the year 2005, where I could bring the company to a higher level in terms of performing software development tasks. There are a lot of things that will need improvements, both on the technical aspect and process/methodologies. Can anyone point me out to a good resource of where to find the best resources for SDLC, processes, and methodologies?

Four major goals I have for the year 2005:
1. SOP, Guidelines & Best Practices for the SDLC
2. Cross-Projects Review based on #1
3. Component libraries from previous projects
4. Support new projects with better SOP, Guidelines, Best Practices, Reviews & Component Libraries

Currently, I find difficulty in which to do first. I believe I should nail #1 down first, then the rest would be easier (more feasible). The company itself is trying to get a SW-CMM Level 3 or 4, so maybe defining #1 may just align with the effort of going SW-CMM itself.

Anyone has a better idea?
It's like having a great chance to start your own company, from scratch, but with experiences (hard earned experiences).
I need to get this one correctly, otherwise I might end up losing another 4-5 years of my life doing something which I might regret.


Further Reading:
CMMI Distilled: A Practical Introduction to Integrated Process Improvement, Second Edition
CMM in Practice: Processes for Executing Software Projects at Infosys