Saturday, September 17, 2011

BigDecimal why and how ?

Hello



In this article, I present some examples how to use BigDicimal Java type.


Problems with Double type in Java



The Double type in Java stores a number in two parts : significant digits et exponent.


Significant digits × base^exponent

That is why it can store a very large number or very small number but it loses precision.

Example

double d = 999888777666555555333222111.0;
System.out.println("my double " + d);

This code prints the following result : 
my double 9.998887776665556E26

In general, when the "significant digits" part is too long, the double type loses precision.

What is why when we add a small number with a big number, the precision is lost (with small number part gets lost).

To avoid the number to be printed with significant/exponent form, we can use DecimalFormat utility.

// this format prints number with optional 2-digit fractional part
  // # = optional part
  //  ex. "12", "12,2", "12,25"  
  static DecimalFormat f = new DecimalFormat("#0.##");

  // this format prints number with 2-digit fractional part
  //  ex. "12,00", "12,20", "12,25"  
  static DecimalFormat f2 = new DecimalFormat("#0.00");


Solution : BigDecimal type

The BigDecimal type stores a number as if it is a string.
It allows us to perform add or subtract operations without losing precision.


Example

double d1 = 1000000000;
  double d2 = 0.000000003;

  double d3 = d1 + d2;

  double d4 = d3 - d1;
  System.out.println("d4=" + d4 + " or " + f.format(d4));

  BigDecimal bc1 = new BigDecimal("1000000000");
  BigDecimal bc2 = new BigDecimal("0.000000003");

  BigDecimal bc3 = bc1.add(bc2);
  BigDecimal bc4 = bc3.subtract(bc1);
  System.out.println("bc4=" + bc4 + " or " + f.format(bc4));

This code prints the following result : 

d4=0.0 or 0
bc4=3E-9 or 0,000000003




Manage precision in division


The division operation oftens make some precision lost, for example 1/3 = 0,33333...
If we truncate the number, we will lose some precision.


The BigDecimal type enables us to specify how long we want to keep the number.
The "scale" parameter specifies the number of digits in the fractional part to keep.
The RoundingMode parameter specifies what to do when the precision lost.
Usually, we can use HALF_UP
(Ex. with scale 2, HALF_UP : 0.128 -> 0,13; 0.123 -> 0.12; 0.125 -> 0.13)

For example, if we calculate 1/3 with scale 4, the result is 0,3333.
We how that the error margin is +/- 0,00005.




This is the complete example code :




import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;

public class TestBigDecimal {

 static DecimalFormat f = new DecimalFormat(
   "#0.#####################################");

 private static void ex1() {

  /*
    this example show how the Double type lose precision 
    when adding big value to small value
   */

  double d1 = 1000000000;
  double d2 = 0.000000003;

  double d3 = d1 + d2;

  double d4 = d3 - d1;
  System.out.println("d4=" + d4 + " or " + f.format(d4));

  BigDecimal bc1 = new BigDecimal("1000000000");
  BigDecimal bc2 = new BigDecimal("0.000000003");

  BigDecimal bc3 = bc1.add(bc2);
  BigDecimal bc4 = bc3.subtract(bc1);
  System.out.println("bc4=" + bc4 + " or " + f.format(bc4));
 }

 private static void ex2() {

  /*
    this example shows how to keep the desired precision when dividing numbers. 
    
   */

  BigDecimal result;

  System.out.println("test 1/2");
  result = new BigDecimal(1).divide(new BigDecimal(2));
  System.out.println("[division without precision lose] result="
    + f.format(result));

  try {
   System.out.println("test 1/3");
   result = new BigDecimal(1).divide(new BigDecimal(3));
   System.out.println("[division with precision lose] result="
     + f.format(result));
  } catch (Exception e) {
   System.out.println("division impossible " + e);
  }

  try {
   System.out.println("test 1/3 with scale 4");
   result = new BigDecimal(1).divide(new BigDecimal(3), 4,
     RoundingMode.HALF_UP);
   System.out.println("[division with scale 4] result="
     + f.format(result));
  } catch (Exception e) {
   System.out.println("division impossible " + e);
  }

  try {
   System.out.println("test 1/3 with scale 5");
   result = new BigDecimal(1).divide(new BigDecimal(3), 5,
     RoundingMode.HALF_UP);
   System.out.println("[division with scale 5] result= "
     + f.format(result));
  } catch (Exception e) {
   System.out.println("division impossible " + e);
  }

  /*
  **************
     Example of division and margin 
  **************
  */

  System.out.println("\n\n" + "Example (bc1/bc2)*bc2 ");

  BigDecimal bc1 = new BigDecimal("777555333.000123456789");
  BigDecimal bc2 = new BigDecimal("999777444");

  System.out.println("Expected result = bc1 = " + f.format(bc1));
  double d = bc1.doubleValue() * bc2.doubleValue() / bc2.doubleValue();
  System.out.println("Double calculation [lose precision] "
    + f.format(d));

  testDivisionWithScale(bc1, bc2, 5);
  testDivisionWithScale(bc1, bc2, 25);
 }

 /**
  * @param args
  */
 public static void main(final String[] args) {

  System.out.println("Example 1");
  ex1();
  System.out.println();

  System.out.println("Example 2");
  ex2();
  System.out.println();
 }

 private static void testDivisionWithScale(final BigDecimal bc1,
   final BigDecimal bc2, final int scale) {
  System.out.println("\n\n" + "Test big decimal calculation with scale "
    + scale);

  BigDecimal result;
  result = bc1.divide(bc2, scale, RoundingMode.HALF_UP);
  System.out.println("division result=" + f.format(result));
  result = bc1.divide(bc2, scale, RoundingMode.HALF_UP).multiply(bc2);
  System.out.println("multiplication result=" + f.format(result)
    + " real error=\n" + f.format(bc1.subtract(result)));

  BigDecimal margin = null;
  margin = new BigDecimal(Math.pow(10, -1 * +(scale)) * 0.5)
    .multiply(bc2);
  System.out
    .println("error margin (max error) +/- \n" + f.format(margin));
 }

}


******* result ********

Example 1
d4=0.0 or 0
bc4=3E-9 or 0,000000003

Example 2
test 1/2
[division without precision lose] result=0,5
test 1/3
division impossible java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
test 1/3 with scale 4
[division with scale 4] result=0,3333
test 1/3 with scale 5
[division with scale 5] result= 0,33333


Example (bc1/bc2)*bc2 
Expected result = bc1 = 777555333,000123456789
Double calculation [lose precision] 777555333,0001235


Test big decimal calculation with scale 5
division result=0,77773
multiplication result=777556911,52212 real error=
-1578,521996543211
error margin (max error) +/- 
4998,8872199999995620798057781308809666143


Test big decimal calculation with scale 25
division result=0,7777284211266157118753721
multiplication result=777555333,0001234567889999646869124 real error=
0,0000000000000000353130876
error margin (max error) +/- 
0,0000000000000000499888722000000019243





In this example, we see that in each calculation step, we can manage the precision.
The real result is between the calculated result +/- error margin.

By augmenting the scale parameter, the error margin reduces.

Wednesday, October 20, 2010

Configuring a data source in Weblogic


One of the Java EE container functionalities is to provide data sources to its deployed applications. The functionality offers flexibility to application configuration. We can switch the system to a new database without impacts on application code.

Securing a Web application with Weblogic

With Weblogic, we can develop a login-based Web application with only little code !
Classical secured Web applications require the following features
  1. Securing communication (HTTPS)
  2. Exploiting users and roles data to protect Web resources.
    • A user is associated with a set of roles (“client” , “staff”, “administrator staff”).
    • The access to Web resources is controlled according to roles. For example,
      • Only grant access to the URL “/manageProductPrices/*” to the administrator staffs.
      • Only grant access to the URL “/manageOrders /*” to the staffs.
      • Grant access to the URL “/clientArea/*” to all logged in clients.
      • Grant access to the URL “/public/*” to everyone.
    • The data about users and roles can be stored on DBMS or an external server such as LDAP.
  1. Offering services to create and update user data (register new users, change password etc).


In this tutorial, I will show you how to realize all these features in a simple way.
Realizing feature 1 (HTTPS) only consists in configuring the Weblogic domain.
For feature 2, we will use the Weblogic Admin Console to create users and roles, to associate controls to Web resources in “web.xml”.
For feature 3, we will externalize users and roles to an external database. Then, it is possible to create customized web pages to edit theses data with your favorite framework (such as struts + hibernate).
This tutorial does not cover the creation of custom applications to edit users’ data. Rather, we will use the Weblogic Admin Console.

Sunday, October 17, 2010

GWT project

Hello

It has been a while since I created a Google code project

This project will contains a set of demo GWT applications for learning how to implement some client rich application features.

The applications are mainly network games (with two parties) !

They are based on a common framework which provide communications (listing online users and exchanging message between users).

The applications are deployed at the Google App Engine server.

http://gwt-cool-sample.appspot.com

This is a screen capture showing how to play Chess and chat at the same time.



The two-person game is not yet finised. However, you can play with the computer at this URL

http://gwt-cool-sample.appspot.com/chess_vs_computer.html


Please write me if you want to join the code project :-)




Creating a Web Service on Weblogic

With Eclipse, we can create and deploy a Web Service in a few minutes. In this tutorial, we will build a service called Document Manager, which enables users to store and retrieve documents on a server.

This tutorial will show you how to do the following tasks.
  • Define an Web Service interface in Java.
  • Implement this interface and deploys the service on Weblogic.
  • Generate a WSDL from the Java interface.
  • Test the service with a Weblogic tool.
  • Generate a client program from the WSDL.

Saturday, October 16, 2010

Installing and configuring the Weblogic server on Eclipse

Oracle Weblogic offers nice Eclipse plugins to developpe Java EE applications. In this post, I will show you how to install the server and to configure it with Eclipse.


Click here to go to the tutorial


Thursday, March 19, 2009

Formattage du code dans le blog

Bonjour,

Voici le premier message dans mon blog !
Je viens de tester un outil très cool qui permet de formater
joliment les codes Java, XML, etc sur le blog (http://code.google.com/p/google-code-prettify/).
Pour utiliser cet outil,
j'ajoute le code HTML suivant dans mon Modèle Blogger.




<link
href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css"
type="text/css" rel="stylesheet" />

<script type="text/javascript"
src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js" >
</script>


<body onload="prettyPrint()" >
...
</body>




Après, dans mon contenu du blog,
je met le code (ex. Java) entre balise < pre >.


<pre class="prettyprint" >
class FirstApp {
public static void main (String[] args){
System.out.println("Hello World");

}
}
</pre>



Et voici le résultat.


class FirstApp {
public static void main (String[] args){
System.out.println("Hello World");

}
}