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 / First Aid / September 2005

Tip: Looking for answers? Try searching our database.

Smart number formatting

Thread view: 
Rob McDonald - 27 Sep 2005 15:35 GMT
Is there a simple way to do 'smart' number formatting in Java?

My program accepts a double as input in a JTextField.  Their input is parsed
and stored in a MySql database through JDBC.  The next time the program is
run, the field is read from the database, and displayed in the JTextField
(in case they want to change it).

Unfortunately, through this process, the number formatting is ugly.

If the user inputs 1.2, the next time around, it displays
1.2000000476837158.  I realize this is due to printing the full floating
point precision, and that the computer can't store 1.2 exactly.

In this case, the easy answer is to format the answer as X.X unfortunately,
then what happens when the user inputs 0.001?  I don't want to restrict or
define the precision of the display, but I want Java to 'realize' that
1.2000000476837158 is a stupid number to display, and that string of six
zeros (or nines or whatever) generally indicates a good place to round.

(I realize I can just leave the field as text, and store the text in the
database, parsing the value when it is used.  I would like to avoid this
because I don't think that storing a number as a string in the database is
particularly elegant.)

Thanks in advance,

        Rob
Oliver Wong - 27 Sep 2005 15:47 GMT
> Is there a simple way to do 'smart' number formatting in Java?
>
[quoted text clipped - 16 lines]
> 1.2000000476837158 is a stupid number to display, and that string of six
> zeros (or nines or whatever) generally indicates a good place to round.

What if the user enters in "1.2000000476837158"? Wouldn't they be pissed off
if the program thought their number was "stupid" and changed it to "1.2"?

> (I realize I can just leave the field as text, and store the text in the
> database, parsing the value when it is used.  I would like to avoid this
> because I don't think that storing a number as a string in the database is
> particularly elegant.)

   While not elegant, at least the solution will be correct.

   Are all your numbers rational (i.e. as opposed to real numbers?) If so,
you might want to look at java.math.BigDecimal.

   - Oliver
Rob McDonald - 27 Sep 2005 16:16 GMT
> What if the user enters in "1.2000000476837158"? Wouldn't they be pissed off
> if the program thought their number was "stupid" and changed it to "1.2"?

A good point, but a highly unlikely scenario in this program.  Especially
considering that a user should have no expectation of 16 significant digits.
In this case, anything the user inputs after the 8th decimal point renders
the same binary representation.

> > (I realize I can just leave the field as text, and store the text in the
> > database, parsing the value when it is used.  I would like to avoid this
> > because I don't think that storing a number as a string in the database is
> > particularly elegant.)
>
>     While not elegant, at least the solution will be correct.

True enough.

I have also considered counting the number of digits the user inputs to the
right of the decimal point.  The input precision could be stored, and then
resurrected as a dynamic rounding limit.  Again, a lot of work for something
that seems simple.

The other approach that might work capitalizes on the fact that the floating
point representation of a number is always within one bit of the true value.
So, the true value is bounded by floating point values one bit higher and
lower than the given representation.  How can these bounds be compared to
figure out the true value?

This basically amounts to losing a bit of precision...  Compare the 31 bit
representation of the number to the 32 bit representation, and keep
everything where the two representations are the same.  31 bits is more than
enough for these purposes.

>     Are all your numbers rational (i.e. as opposed to real numbers?) If so,
> you might want to look at java.math.BigDecimal.

Well, it is impossible for a human to type in an irrational number as input
(who would have the time (:) so that would work.  However, it would still
require me to store a string of integers in the database.  So, I might as
well stick with a simpler solution.

        Rob
Thomas Schodt - 27 Sep 2005 16:37 GMT
> The other approach that might work capitalizes on the fact that the floating
> point representation of a number is always within one bit of the true value.
[quoted text clipped - 6 lines]
> everything where the two representations are the same.  31 bits is more than
> enough for these purposes.

A double is 64 bit wide (1 sign, 11 exponent, 52 mantissa).
Rob McDonald - 27 Sep 2005 17:16 GMT
> > The other approach that might work capitalizes on the fact that the floating
> > point representation of a number is always within one bit of the true value.
[quoted text clipped - 8 lines]
>
> A double is 64 bit wide (1 sign, 11 exponent, 52 mantissa).

Ok, but the point still holds.  (and maybe my precision is being truncated
by the storage in MySql.)

A 64 bit double is only accurate to the 52'nd bit of the mantissa.  If I
created a 63 bit floating point number, (1,11,51) it would only be slightly
less accurate than the 64 bit number, and comparing the two values may shed
light on the 'smart' formatting that I want.

       Rob
Oliver Wong - 28 Sep 2005 17:42 GMT
>> What if the user enters in "1.2000000476837158"? Wouldn't they be pissed
> off
[quoted text clipped - 5 lines]
> In this case, anything the user inputs after the 8th decimal point renders
> the same binary representation.

   If you want your software to be robust, it must perform within
specifications even in "highly unlikely scenarios".

> I have also considered counting the number of digits the user inputs to
> the
> right of the decimal point.  The input precision could be stored, and then
> resurrected as a dynamic rounding limit.  Again, a lot of work for
> something
> that seems simple.

   This will fail if the stored number of significant digits is greater
than the number of digits which are significant in the decimal
representation of a float or double. E.g. if the user enters in a number
with 20 significant digits after the decimal point, you might store the fact
that there's 20 significant decimal digits after the decimal point, but as
soon as you're storing the original value entered by the user itself in a
double, you no longer have those 20 digits.

   But yes, this is a lot of work when you could just, for example, store
the numbers as BigDecimals or as Strings.

> The other approach that might work capitalizes on the fact that the
> floating
[quoted text clipped - 3 lines]
> lower than the given representation.  How can these bounds be compared to
> figure out the true value?

   Impossible. There are an infinite number of rational values between your
two bounds, any of which could have been the "true value".

> This basically amounts to losing a bit of precision...  Compare the 31 bit
> representation of the number to the 32 bit representation, and keep
> everything where the two representations are the same.  31 bits is more
> than
> enough for these purposes.

   You might need to go back and look at your product's requirements.
Floating points (i.e. float and double) are great when precision isn't
critical. Not so great when rounding errors can lead to disaster (e.g.
dealing with financial data). What do you need for your program to work?

>>     Are all your numbers rational (i.e. as opposed to real numbers?) If
> so,
[quoted text clipped - 5 lines]
> require me to store a string of integers in the database.  So, I might as
> well stick with a simpler solution.

   I vaguely recall Java's BigDecimal type to map cleanly onto SQL's
DECIMAL type. You'd have to consult your documentation to verify this
though.

   - Oliver
Eric Sosman - 27 Sep 2005 17:22 GMT
Rob McDonald wrote On 09/27/05 10:35,:
> Is there a simple way to do 'smart' number formatting in Java?
>
[quoted text clipped - 19 lines]
> because I don't think that storing a number as a string in the database is
> particularly elegant.)

   I'm not sure why you consider text inelegant.  You
receive the value as text, and you want to turn around
and display it again as text: why convert to and from
double, or Gray code, or anything else?  Note that your
troubles stem purely from the conversion back and forth:
your woes are, er, "elegantly self-inflicted."

   Omitting the gratuitous conversion avoids some of
the problems you have brought upon yourself: for example,
text can represent 1.2 with perfect accuracy.  Text can
also preserve the distinctions between 01 and 1 and 1.0,
if that's interesting to your users.

   I'd suggest re-examining what the stored values are
intended for.  If there's a really good reason to store
them as converted numbers, then by all means do so -- but
it might not hurt to store the original text, too, as the
"authoritative source" from which the numbers are derived.
It's really a matter of your application's needs.

Signature

Eric.Sosman@sun.com

Rob McDonald - 27 Sep 2005 21:35 GMT
Thanks for all the suggestions,

As it turns out, the center of my problem was the transition between Java &
MySql.

I am sending my Java double's to MySql floats via JDBC.  (This is the
reccomended Java type to use for the JDBC type.)

But, MySql is storing a 32 bit floating point number.  When I read it back,
Java's 64 bit number has plenty of precision, and thinks those digits are
significant.  So, Double.toString(x) gives me the garbage at the end.
(where x is a double).

However, if I do a Float.toString((float) x); this parser is smart enough to
'just work' the way I want.

Thanks,

        Rob


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.