Join wMUsers | Blog at wMUsers | User Control Panel | Site Map | webMethods Jobs |For Employers

Rob Eamon -- webMethods Ezine Columnist

Float and Double: 1/3 + 2/3



By Rob Eamon

 

"Most terminating decimal fractions cannot be exactly represented as terminating binary fractions."

Joe Darcy, Java Floating-Point Czar
Sun Microsystems, JavaOne 2001 Presentation
(http://java.sun.com/people/darcy/JavaOne/2001/1789darcy.pdf)

Floating Point Arithmetic is Inexact

Working with fractions in computers can be dangerous. Floating point arithmetic often stuns developers with its seemingly erroneous results.

What does Joe Darcy’s statement above mean exactly? As an example, consider the decimal fraction 0.1. It cannot be exactly represented as a binary fraction. In binary, decimal 0.1 is the repeating fraction 0.0001100110011...   The exact value of 0.1f after conversion to decimal format is 0.100000001490116119384765625 while the decimal conversion of the double 0.1d is 0.1000000000000000055511151231. Clearly this can cause some unanticipated results.

Roedy Green’s Java Glossary (http://mindprod.com/jglossfloatingpoint.html) discusses floating point in Java at some length. He offers insight on why developers should not be surprised at the inaccuracy of floating point:

    [0.1 is a repeater fraction in binary.] It is like the repeater fraction 1/3 = 0.33333 in base 10. When you add 0.333333... to 0.666666... why are you not astonished to get 0.999999... rather than 1.0, even though you just added 1/3 + 2/3 to get 1? Yet, with Java floating point you are astonished when you add 0.1 + 0.1 and get something other than 0.2.

It is clear that when using float and double types in Java, some care must be taken to ensure proper behavior for the task at hand. For financial applications, where accuracy is paramount, float and double may need to be avoided altogether.

How does this impact webMethods developers? The Integration Server and Broker environments both support floating-point data types. And, consequently, each environment presents opportunities to inadvertently introduce floating-point inaccuracies into your integrations.


Integration Server

IS treats all data as text. Data elements are referenced as String objects unless explicitly treated as something else (i.e. Object types in the pipeline). It is within Java services, though, floating point errors might be introduced. For example, using the built-in service pub.math:addFloats to add the values 0.111 and 0.456 does not return a value of 0.567 as expected. Rather, the result is 0.5670000000000001.

This is not a webMethods built-in service bug. It is the result of parsing the two numbers to double (not floats -- using floats results in 0.56700003) and adding them. You can confirm this behavior in your own favorite Java environment with the following sample code:

    double a = 0.111d;
    double b = 0.456d;
    double c = a + b;
    System.out.println(c);  // will print 0.5670000000000001
    

All of the webMethods built-in services that operate on floats may return inaccurate results. For some integrations, this can be a devastating effect -- and it can be avoided. A replacement set of services using the BigDecimal class can be built and will provide accurate results. Here is the source for a service named addDecimals that can function as a replacement for the addFloats service:

    IDataCursor pipelineCursor = pipeline.getCursor();
    String num1 = IDataUtil.getString(pipelineCursor, "num1");
    String num2 = IDataUtil.getString(pipelineCursor, "num2");
    
    // Note that these constructors may throw NPE if
    // num1 and/or num2 are not passed to the service.
    // This mimics pub.math:addFloats.
    
    java.math.BigDecimal n1 = new java.math.BigDecimal(num1);
    java.math.BigDecimal n2 = new java.math.BigDecimal(num2);
    java.math.BigDecimal value = n1.add(n2);
    
    IDataUtil.put(pipelineCursor, "value", value.toString());
    pipelineCursor.destroy();

The service can be enhanced by adding a scale parameter (to set the number of decimal places), and possibly a rounding parameter (to set the rounding mode to be used in the result). Services for subtracting, multiplying and dividing can be built as well and are similar in construct.



[1]  2  Next>>

Go Deeper on the Subject: The wMUsers Discussion Forums


Rob Eamon is a consultant with SBI and Company and has over 17 years experience in IT-related areas. He has completed several successful integration projects using the webMethods Platform.

Rob can be reached via email at


Advertise at wMUsers






  Home | Join wMUsers | Discussion Forums | Knowledge Center | Jobs | Shareware | User Groups | Links |
Contact Us | Terms of Service | Privacy Policy

wMUsers is an independent organization and is not sponsored in any manner by Software AG.


© All Rights Reserved, 2001-2008.