Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / General / March 2006

Tip: Looking for answers? Try searching our database.

Recovering formatted double

Thread view: 
Richard F.L.R.Snashall - 21 Mar 2006 04:39 GMT
In application code, I have code to format a double into
a String:

   double db = 12.34;

   java.text.DecimalFormat fourdigits =
      new java.text.DecimalFormat( "0.0000" );

   string db_in_string = " " + fourdigits.format( db );

and later, to recover the double:

   double recovered_db;

   try
       {
       recovered_db = Double.parseDouble( db_in_string );
       }
   catch( NumberFormatException numberFormatException )
       {
       // Generate error message
       ...

       return;
       }

I have a client in another country, however, that is having
trouble getting this code to function.  Either they have to
initiate overriding the locale with English, or hand-correct
any values that are set (changing "," to ".", I believe).

How do I get this to function?  It was my understanding that
Double.parseDouble was locale insensitive and would trim
any leading and trailing spaces.
Dimitri Maziuk - 21 Mar 2006 04:53 GMT
Richard F.L.R.Snashall sez:
> In application code, I have code to format a double into
> a String:
[quoted text clipped - 30 lines]
> Double.parseDouble was locale insensitive and would trim
> any leading and trailing spaces.

The obvious answer would be to pass around a Double instead
of a String.

Dima
Signature

The speed at which a mistyped command executes is directly proportional
to the amount of damage done.                                       -- Joe Zeff

Richard F.L.R.Snashall - 21 Mar 2006 05:22 GMT
> Richard F.L.R.Snashall sez:
>>
[quoted text clipped - 4 lines]
> The obvious answer would be to pass around a Double instead
> of a String.

Not applicable.  The string is sent to a user-modifiable text
field and recovered later (if not modified, of course).
Dimitri Maziuk - 21 Mar 2006 18:30 GMT
Richard F.L.R.Snashall sez:
>> Richard F.L.R.Snashall sez:
>>>
[quoted text clipped - 7 lines]
> Not applicable.  The string is sent to a user-modifiable text
> field and recovered later (if not modified, of course).

In which case you want to make sure you're printing it out
in the default locale and reading it back in in the default
locale. Probably using DecimalFormat for both printing and
parsing.

IIRC Double.parseDouble() is pretty dumb: it won't read
scientific notation and I don't think it'll trim whitespace
either.

Dima
Signature

...the mainstream products of major vendors largely ignore these demonstrated
technologies...  [Instead, their customers] are left with several ineffective
solutions collected under marketing titles like "defense in depth".
        -- Thirty Years Later: Lessons from the Multics Security Evaluation

Stefan Ram - 21 Mar 2006 05:00 GMT
>java.text.DecimalFormat fourdigits =
>new java.text.DecimalFormat( "0.0000" );

 You could fix the locale to a specific local such as
 »java.util.Locale.US« by using something like:

public class Main
{ public static void main( final java.lang.String[] args )
 throws java.lang.Throwable
 { final java.text.NumberFormat numberFormat =
   java.text.NumberFormat.getInstance
   ( java.util.Locale.US );
   numberFormat.setMinimumFractionDigits( 4 );
   numberFormat.setMaximumFractionDigits( 4 );
   final java.lang.String text = numberFormat.format( 1.2345 );
   final double number = numberFormat.parse( text ).doubleValue();
   java.lang.System.out.println( number ); }}
Thomas G. Marshall - 21 Mar 2006 05:12 GMT
Stefan Ram said something like:
>> java.text.DecimalFormat fourdigits =
>> new java.text.DecimalFormat( "0.0000" );
>
>  You could fix the locale to a specific local such as
>  »java.util.Locale.US« by using something like:

That is not what he wants.  If his code were to use the default locale:

   NumberFormat nf = NumberFormat.getInstance(); // no param

Then the code would work properly no matter /where/ it was.  If it were run
in England, it would allow

   3,14159

for example.

NOTE: I've said this a million times in the past.  If you are formatting or
parsing something that a user might enter, then you should always use
NumberFormat (or a derivative).

You will never know when a user might enter in 1,000 for 1000, or any number
of other digit grouping rules, many of which you might never guess at; they
are that weird.

> public class Main
> { public static void main( final java.lang.String[] args )
[quoted text clipped - 7 lines]
>    final double number = numberFormat.parse( text ).doubleValue();
>    java.lang.System.out.println( number ); }}

Signature

"Realtor" and "realty" are pronounced "reel'-tor" and
"reel'-tee", *not* "reel'-a-tor" and "reel'-i-tee" !!!!
If you pronounce them with the extra syllable, you will
sound like a complete idiot.

Richard F.L.R.Snashall - 21 Mar 2006 05:30 GMT
> Stefan Ram said something like:
>
[quoted text clipped - 18 lines]
> parsing something that a user might enter, then you should always use
> NumberFormat (or a derivative).

This is where I started to get lost.  The manual page says the method is
"static NumberFormat getInstance( )".  Does that mean that the same
static value is always passed back?  If so, how do I then make my own
copies?  In the example I gave, I used four digits, but I also needed
other numbers of digits.

If I may, another question; why not getNumberInstance, since my
application is numeric only.

> You will never know when a user might enter in 1,000 for 1000, or any number
> of other digit grouping rules, many of which you might never guess at; they
> are that weird.
Roedy Green - 21 Mar 2006 07:38 GMT
On Mon, 20 Mar 2006 23:30:54 -0500, "Richard F.L.R.Snashall"
<rflrs@notnotrcn.com> wrote, quoted or indirectly quoted someone who
said :

>If I may, another question; why not getNumberInstance, since my
>application is numeric only.
just use new DecimalFormat
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Thomas G. Marshall - 23 Mar 2006 06:27 GMT
Richard F.L.R.Snashall said something like:
>> Stefan Ram said something like:
>>
[quoted text clipped - 26 lines]
> copies?  In the example I gave, I used four digits, but I also needed
> other numbers of digits.

No, no, the format itself that you're using changes as you specify it.
Ok, here's the way it was designed, which I'm not particularly thrilled
with, but it's "eh, ok".

NumberFormat is an abstract class.  It contains the factory methods for
instantiating it's various subclasses.

The various getInstance() methods defined with NumberFormat (see some below)
all call a private getInstance() which takes the desired locale and format
style (see below as well).  The private getInstance() employs a cache of
number patterns.  Don't ask me why this was considered so critical: I can't
imagine that any of this would have been trouble without the cache.

I would avoid direct instantiation of the various number formats, however,
only for maintainability reasons.  Most coders are used to seeing one of the
NumberFormat factory methods used...

> If I may, another question; why not getNumberInstance, since my
> application is numeric only.

More factory method hooey.  Just getInstance() will be fine, it is
equivalent.

Here, this is what the code actually looks like for those factory methods
within NumberFormat (jdk 5.0).  Note that NUMBERFORMAT is one of the "type"
constants:

<elsewhere in NumberFormat.java>
   // Constants used by factory methods to specify a style of format.
   private static final int NUMBERSTYLE = 0;
   private static final int CURRENCYSTYLE = 1;
   private static final int PERCENTSTYLE = 2;
   private static final int SCIENTIFICSTYLE = 3;
   private static final int INTEGERSTYLE = 4;
</elsewhere>

<factory methods>
   /**
    * Returns a general-purpose number format for the current default
locale.
    * This is the same as calling
    * {@link #getNumberInstance() getNumberInstance()}.
    */
   public final static NumberFormat getInstance() {
       return getInstance(Locale.getDefault(), NUMBERSTYLE);
   }

   /**
    * Returns a general-purpose number format for the specified locale.
    * This is the same as calling
    * {@link #getNumberInstance(java.util.Locale)
getNumberInstance(inLocale)}.
    */
   public static NumberFormat getInstance(Locale inLocale) {
       return getInstance(inLocale, NUMBERSTYLE);
   }

   /**
    * Returns a general-purpose number format for the current default
locale.
    */
   public final static NumberFormat getNumberInstance() {
       return getInstance(Locale.getDefault(), NUMBERSTYLE);
   }

   /**
    * Returns a general-purpose number format for the specified locale.
    */
   public static NumberFormat getNumberInstance(Locale inLocale) {
       return getInstance(inLocale, NUMBERSTYLE);
   }
</factory>

..............more hooey..............and here is the private method I was
talking about:

   private static NumberFormat getInstance(Locale desiredLocale,
                                          int choice) {
       /* try the cache first */
       String[] numberPatterns =
(String[])cachedLocaleData.get(desiredLocale);
       if (numberPatterns == null) { /* cache miss */
           ResourceBundle resource =
LocaleData.getLocaleElements(desiredLocale
);
           numberPatterns = resource.getStringArray("NumberPatterns");
           /* update cache */
           cachedLocaleData.put(desiredLocale, numberPatterns);
       }

       DecimalFormatSymbols symbols = new
DecimalFormatSymbols(desiredLocale);
       int entry = (choice == INTEGERSTYLE) ? NUMBERSTYLE : choice;
       DecimalFormat format = new DecimalFormat(numberPatterns[entry],
symbols)
;

       if (choice == INTEGERSTYLE) {
           format.setMaximumFractionDigits(0);
           format.setDecimalSeparatorAlwaysShown(false);
           format.setParseIntegerOnly(true);
       } else if (choice == CURRENCYSTYLE) {
           format.adjustForCurrencyDefaultFractionDigits();
       }

       return format;
   }

Signature

Everythinginlifeisrealative.Apingpongballseemssmalluntilsomeoneramsitupyournose.

Richard F.L.R.Snashall - 23 Mar 2006 06:57 GMT
> Richard F.L.R.Snashall said something like:

>         DecimalFormat format = new DecimalFormat(numberPatterns[entry],
> symbols)
> ;

That's the first piece I was missing... the alternate formulation
of the DecimalFormat constructor with the DecimalFormatSymbols...
and then using a DecimalFormat method to parse the input as well,
so the input format matched the output format.
Thomas Hawtin - 21 Mar 2006 19:55 GMT
> Stefan Ram said something like:
>>  »java.util.Locale.US« by using something like:
[quoted text clipped - 7 lines]
>
>     3,14159

We use comma as a thousand separator over here in the UK locale. So
that, as in the US locale, is interpreted as 314,159.0.

In the UK, we do use a decimal point (a dot raised to the middle level
of a digit character) as a decimal point. However, localisation tends to
ignore that and go for what I assume is a vulgar Americanism.

Tom Hawtin
Signature

Unemployed English Java programmer
http://jroller.com/page/tackline/

Roedy Green - 21 Mar 2006 23:41 GMT
On Tue, 21 Mar 2006 18:55:46 +0000, Thomas Hawtin
<usenet@tackline.plus.com> wrote, quoted or indirectly quoted someone
who said :

>In the UK, we do use a decimal point (a dot raised to the middle level
>of a digit character) as a decimal point. However, localisation tends to
>ignore that and go for what I assume is a vulgar Americanism.

does localisation know about that?

One problem with implementing that is raised dot has less font support
than period.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Roedy Green - 21 Mar 2006 07:37 GMT
>  You could fix the locale to a specific local such as
>  »java.util.Locale.US« by using something like:

There are also DecimalFormat.setDecimalFormatSymbols to override the
locale defaults:

But the easy way is to use a binary DataOutputStream which is
locale-independent.

see http://mindprod.com/applets/fileio.html for sample code.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Java custom programming, consulting and coaching.

Richard F.L.R.Snashall - 21 Mar 2006 19:42 GMT
>>java.text.DecimalFormat fourdigits =
>>new java.text.DecimalFormat( "0.0000" );
[quoted text clipped - 13 lines]
>     final double number = numberFormat.parse( text ).doubleValue();
>     java.lang.System.out.println( number ); }}

I chose close to this:

    // test version

    final java.util.Locale myLocale = new java.util.Locale( "de" );

    // final version

    final java.util.Locale myLocale = java.util.Locale.getDefault( );

then, for formatting:

    private java.text.NumberFormat digsFormat =
      java.NumberFormat.getInstance( myLocale );

and:

    digsFormat.setMinimumFractionDigits( 1 );
    digsFormat.setMaximumFractionDigits( 4 );

and finally:

    db_in_string = digsFormat( db );

For recovery, I mimicked Double.parseDouble with another function:

    public java.text.NumberFormat DFormat =
      java.text.NumberFormat.getInstance( myLocale );
    public java.text.ParsePosition DPosition =
      new java.text.ParsePosition( 0 );

    public double DparseDouble( String S ) throws NumberFormatException
      {
      String T = S.trim( );
      DPosition.setIndex( 0 );
      Number parsedNumber = DFormat.parse( T, DPosition );

      if( DPosition.getIndex( ) < T.length( ) )
        {
        throw new NumberFormatException( );
        }

      return parsedNumber.doubleValue( );
      }

My thanks to all for your help.
Richard F.L.R. Snashall - 21 Mar 2006 23:55 GMT
>>java.text.DecimalFormat fourdigits =
>>new java.text.DecimalFormat( "0.0000" );
[quoted text clipped - 13 lines]
>     final double number = numberFormat.parse( text ).doubleValue();
>     java.lang.System.out.println( number ); }}

(My ISP may get around to sending the original of this later;-)

I chose close to this:

    // test version

    final java.util.Locale myLocale = new java.util.Locale( "de" );

    // final version

    final java.util.Locale myLocale = java.util.Locale.getDefault( );

then, for formatting:

    private java.text.NumberFormat digsFormat =
      java.NumberFormat.getInstance( myLocale );

and:

    digsFormat.setMinimumFractionDigits( 1 );
    digsFormat.setMaximumFractionDigits( 4 );

and finally:

    db_in_string = digsFormat( db );

For recovery, I mimicked Double.parseDouble with another function:

    public java.text.NumberFormat DFormat =
      java.text.NumberFormat.getInstance( myLocale );
    public java.text.ParsePosition DPosition =
      new java.text.ParsePosition( 0 );

    public double DparseDouble( String S ) throws NumberFormatException
      {
      String T = S.trim( );
      DPosition.setIndex( 0 );
      Number parsedNumber = DFormat.parse( T, DPosition );

      if( DPosition.getIndex( ) < T.length( ) )
        {
        throw new NumberFormatException( );
        }

      return parsedNumber.doubleValue( );
      }

My thanks to all for your help.
Richard F.L.R.Snashall - 22 Mar 2006 22:19 GMT
> For recovery, I mimicked Double.parseDouble with another function:
>
[quoted text clipped - 16 lines]
>       return parsedNumber.doubleValue( );
>       }

Oops! It needs an additional check for a zero length trimmed
string.
Filip Larsen - 21 Mar 2006 07:25 GMT
> In application code, I have code to format a double into
> a String. [...]
> I have a client in another country, however, that is having
> trouble getting this code to function.

Use could your own DecimalFormat to format double string and use a
NumberFormat.getNumberInstance() to parse it back in. Or perhaps better,
round the double internally to the number of decimals you want and then
use NumberFormat.getNumberInstance() to both format and parse the
string.

Regards,
Signature

Filip Larsen



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.