2

As part of a larger program, I have this function that, when called, returns the string under return. accountHolder, balance, interestRate, and points are variables in an object of type RewardsCreditAccount. So, for example, I declare an object here:

RewardsCreditAccount testAccount = new RewardsCreditAccount("Joe F. Pyne", 7384.282343837483298347, 0.173, 567);

So this object will set accountHolder = "Joe F. Pyne", balance = 7384.282343837483298347, and so on.

In the function below, I return this information in a string that should look like this:

Joe F. Pyne, $7384.282, 17.28%, 567 points

Using this function:

    public String toString() {
    return (accountHolder + ", $" +  + balance + 100*interestRate + "%, " + points + " points");
}

However, it is in fact returning this:

Joe F. Pyne, $7384.282, 17.299999999999997%, 567 points

I tried this, but to no avail

public String toString() {
    return (accountHolder + ", $" +  + ("%,1.2f",balance) + 100*interestRate + "%, " + points + " points");
}

This is rather annoying, because I want it to only return two decimal places. I know this can be done using %1.2f, but I have no idea how to format the syntax for that. I would vastly appreciate any help on getting the decimal value to display properly. Thanks!

ppeterka
  • 20,583
  • 6
  • 63
  • 78
Kyle Evans
  • 149
  • 1
  • 6
  • 4
    You should use BigDecimal for monetary calculations, not doubles... – assylias Oct 15 '12 at 08:10
  • Agreed, but this is for a class and part of the program was given to me that I can't change. That includes the part of using doubles for money. – Kyle Evans Oct 15 '12 at 08:11
  • try String.format() its just like printf() in C. – pratZ Oct 15 '12 at 08:15
  • There is no such thing as a 'double as part of a larger string', and you should refuse any assignment that involves using floating-point for money. – user207421 Oct 15 '12 at 09:15
  • See also http://stackoverflow.com/questions/10959424/show-only-two-digit-after-decimal but not a duplicate of that, because the value is wanted as part of a longer string. – Raedwald Apr 03 '14 at 12:04

4 Answers4

6

You'll have to use String.format(); with that format-String.

So this

public String toString() {
    return (accountHolder + ", $" +  + ("%,1.2f",balance) + 100*interestRate + "%, " + points + " points");
}

Should be:

public String toString() {
    return String.format("%s, $%,1.2f %s%%, %s points", accountHolder, balance, 100*interestRate, points );
}

With the formatters set so that it is printed according to your desires.

Fildor
  • 14,510
  • 4
  • 35
  • 67
  • This is outputting: Joe F. Pyne, $7,384.28 17.299999999999997%, 567 points Why is it printing the interestRate in such a weird way? – Kyle Evans Oct 15 '12 at 08:22
  • 1
    BTW: instead of `%,1.2f` you can write `%,.2f` as the `1` doesn't do anything here. – Peter Lawrey Oct 15 '12 at 08:23
  • The formatters might still not be correct. I inteded to point out the use of `String.format` – Fildor Oct 15 '12 at 08:23
  • Ah, okay. Where can I learn about the different characters that format them? – Kyle Evans Oct 15 '12 at 08:24
  • @PeterLawrey I tried the solution posted by Fildor, and while it printed the balance properly, the interestRate now prints really oddly. – Kyle Evans Oct 15 '12 at 08:25
  • For example here: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html#syntax I try to find a more recent one ... – Fildor Oct 15 '12 at 08:26
  • What do you mean by "oddly"? What is the type of this field, what did you see and what did you expect? – Peter Lawrey Oct 15 '12 at 08:26
  • 1
    @Fildor. Were you searching for this one - http://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html – Rohit Jain Oct 15 '12 at 08:27
  • @PeterLawrey When I run it, I'm expecting it to print: "Joe F. Pyne, $7,384.28 17.3%, 567 points". What actually happens though is that it prints: "Joe F. Pyne, $7,384.28 17.299999999999997%, 567 points". So, the .3 in interestRate gets turned into .2999999999999 for some reason. – Kyle Evans Oct 15 '12 at 08:28
  • Yes @RohitJain and Peter. But it's actually the same content. – Fildor Oct 15 '12 at 08:30
  • 1
    @KyleEvans That's because of the %s. It means that it is formatted as a string. Try a number format here, too. That is %.2f for example. Depending on what type interest rate is. And the .9999.. is rounding error. Working with floating point numbers can be surprising sometimes :) – Fildor Oct 15 '12 at 08:31
  • Good reference on floating point numbers : [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) – Fildor Oct 15 '12 at 08:36
5

Use DecimalFormater for formatting your value.

new DecimalFormat("###.##").format(17.299999999999997);

For reference.

Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103
4

You will need to use String.format() to format your returned String: -

String.format("%5.2f",balance)
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525
1

Floating point numbers are not always easy to deal with.

Your problem lies in the fact that floating point types (as float and double, and their boxed counterparts) are just binary approximations of their decimal representation, so all kinds of such problems can arise when not taking this into count.

You also have to pay attention when handling very large values, because it can occur that (a== (a+1))==true...

Also, for currencies, and other such critical data, I'd recommend BigDecimal, which stores the exact string representation, not the binary approximation. That is not the most trivial thin on Earth to handle though, but given the criticality of data, I think it is unavoidable.

ppeterka
  • 20,583
  • 6
  • 63
  • 78