11152

Java : How to count the number of decimals contained in a double value that represent money?

Question:

For a change-making application, made with Java, I am facing a problem while counting the number of decimals in a double value.

The double value represent money, so all my operations must be made in consequences that a double value like 12.58 can be stored as 12.5797886 after an operation is made on the original value. To counter this effect, I chose to use String, just like this :

String amountString = String.valueOf(amount); String decimals = amountString.substring(amountString.indexOf('.') + 1);

So if the amount is 12.58, I obtain 58 and not 57978...

My problem is concerning big amount, just like 12849561476651.2501535 A such amount is converted in scientific notation while stored in a double. So the double value of the amount would be 1.284956147665125E13

Unfortunately I can't just count the number after the dot and take everything after the position 13. In a situation just like this one, where the original decimals 2501535 contains a 0 at the third position, the result after the position 13 is rounded to 25.

I found some solution for people who want to print a decimal value without the scientific notation, they use .printf( %f , ... ) or something similar.

But, if it is possible, how can I count the number of decimals contained in a double value and take care of the storage problem and the scientific notation?

I must be able to know if there is more than 2 decimals. In addition, if you have a pretty performant solution, even if it is a complex or a strange one, it would be great.

Thank you

Answer1:

Do not use double or float to store currency, or to store any decimal numbers that need to be exact, as double and float can be inaccurate.

You can use BigDecimal or else use an int or a long and keep track of the decimal point yourself.

For more info on this, see the section "Item 48: Avoid float and double if exact answers are required" in Effective Java by Joshua Bloch: <a href="http://uet.vnu.edu.vn/~chauttm/e-books/java/Effective.Java.2nd.Edition.May.2008.3000th.Release.pdf" rel="nofollow">http://uet.vnu.edu.vn/~chauttm/e-books/java/Effective.Java.2nd.Edition.May.2008.3000th.Release.pdf</a>

Answer2:

Don't use a float or double for financial operations. It is better to use a BigDecimal. A BigDecimal give you the precision that you need. From the javadoc:

<blockquote>

arbitrary-precision signed decimal numbers

</blockquote>

The double will generate errors due to the approximation of the internal binary representation of doubles. Also for very small values it can generate errors that are very difficult to find.

Answer3:

You can't. Floating point doesn't have decimal places. It has binary places, and they are not commensurable with decimal places. If you want decimal places you must use a decimal radix.

Use BigDecimal.

<strong>EDIT</strong> In a paragraph that you added since this answer and which you have now deleted, you state that the number comes from the UI. In which case it is a String at that point, which is already in radix-10, so you should just be counting decimal places <em>in the String,</em> and not converting it to a double at all.

Recommend

  • Duplicate javascript for Codrops MULTI-LEVEL PUSH MENU
  • How to pass DataFrame as input to Spark UDF?
  • Incrementing array values - Arduino
  • Storing large decimal numbers in Java
  • Cassandra CQL paging for Composite key
  • Check if NSString hasPrefix that is contained in NSArray
  • Adding and multiplying columns of a numpy array with another array
  • How do I get the second integer in a Ruby string with to_i?
  • How to define matching axis notches from existing “step list”
  • different results with and without SSE ( float arrays multiplication)
  • AngularJS - ngBind and Bootstrap Switch
  • python struct.pack(): pack multiple datas in a list or a tuple
  • How to extract a plane from a 3D variable in FiPy (3D to 2D)
  • How is SLOC counted by Delphi IDE?
  • Ray-tracing triangles
  • Is a .txt file created in VB different than one I'd randomly create?
  • Best way to produce 'colour correct' raster from a PDF or PS with ghostscript
  • How to remove the dot in to_char if the number is an integer
  • When executing an array of tasks asynchronously, shouldn't it take as long as the longest runni
  • Reading space separated values file in c++ error
  • Default parameter as generic type
  • Zoom in and out of jPanel
  • Z3: Convert between FP and BitVector?
  • Blackberry - Custom EditField Cursor
  • MVC3 Razor - ListBox pre-select not working
  • Body moving without any force applied? (Box2d)
  • Why HTML5 Canvas with a larger size stretch a drawn line?
  • JavaScriptCore crash on iOS9
  • Excel - Autoshape get it's name from cell (value)
  • Check if a string to interpolate provides expected placeholders
  • SVN: Merging two branches together
  • RestKit - RKRequestDelegate does not exist
  • php design question - will a Helper help here?
  • Traverse Array and Display in markup
  • How to format a variable of double type
  • Transpose CSV data with awk (pivot transformation)
  • AngularJs get employee from factory
  • Android Google Maps API OnLocationChanged only called once
  • IndexOutOfRangeException on multidimensional array despite using GetLength check
  • Authorize attributes not working in MVC 4