6

I'm trying to learn to use namespaces declarations more definitive than not just say "using namespace std". I'm trying to format my data to 2 decimal places, and set the format to be fixed and not scientific. This is my main file:

#include <iostream>
#include <iomanip>

#include "SavingsAccount.h"
using std::cout;
using std::setprecision;
using std::ios_base;

int main()
{
    SavingsAccount *saver1 = new SavingsAccount(2000.00);
    SavingsAccount *saver2 = new SavingsAccount(3000.00);

    SavingsAccount::modifyInterestRate(.03);

    saver1->calculateMonthlyInterest();
    saver2->calculateMonthlyInterest();

    cout << ios_base::fixed << "saver1\n" << "monthlyInterestRate: " << saver1->getMonthlyInterest()
        << '\n' << "savingsBalance: " << saver1->getSavingsBalance() << '\n';
    cout << "saver2\n" << "monthlyInterestRate: " << saver2->getMonthlyInterest()
        << '\n' << "savingsBalance: " << saver2->getSavingsBalance() << '\n';
}

On Visual Studio 2008, when I run my program, I get an output of "8192" before the data I want. Is there a reason for that?

Also, I don't think I am setting the fixed part or 2 decimal places correctly since I seem to get scientific notation once I added the setprecision(2). Thanks.

Crystal
  • 28,460
  • 62
  • 219
  • 393
  • Does this answer your question? [Effective use of C++ iomanip library](https://stackoverflow.com/questions/5328411/effective-use-of-c-iomanip-library) – pradeexsu Oct 27 '20 at 03:54

3 Answers3

5

You want std::fixed (the other one just inserts its value into the stream, which is why you see 8192), and I don't see a call to std::setprecision in your code anywhere.
This'll fix it:

#include <iostream>
#include <iomanip>

using std::cout;
using std::setprecision;
using std::fixed;

int main()
{
    cout << fixed << setprecision(2)
         << "saver1\n" 
         << "monthlyInterestRate: " << 5.5 << '\n' 
         << "savingsBalance: " << 10928.8383 << '\n';
    cout << "saver2\n" 
         << "monthlyInterestRate: " << 4.7 << '\n' 
         << "savingsBalance: " << 22.44232 << '\n';
}
tzaman
  • 46,925
  • 11
  • 90
  • 115
3

It might not be the answer you're looking for, but floating-point numbers are not suited to financial calculations because fractions like 1/100 cannot be represented exactly. You might be better off doing the formatting yourself. This can be encapsulated:

class money {
    int cents;
public:
    money( int in_cents ) : cents( in_cents ) {}

    friend ostream &operator<< ( ostream &os, money const &rhs )
        { return os << '$' << m.cents / 100 << '.' << m.cents % 100; }
};

cout << money( 123 ) << endl; // prints $1.23

Better(?) yet, C++ has a facility called the monetary locale category which includes a money formatter which takes cents as an argument.

locale::global( locale("") );
use_facet< money_put<char> >( locale() ).put( cout, false, cout, ' ', 123 );

This should Do the Right thing internationally, printing the user's local currency and hiding the number of decimal places from your implementation. It even accepts fractions of a cent. Unfortunately, this does not seem to work on my system (Mac OS X), which has generally poor locale support. (Linux and Windows should fare better.)

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • `money_put` variant prints `123` instead of `$1.23` on my machine. It should not be acceptable output on any locale. – jfs Apr 28 '10 at 09:44
  • @J.F. - The expected output is `$1.23`. What platform are you using? – Potatoswatter Apr 28 '10 at 16:15
  • @J.F. That's unfortunate, but it only means that your platform is broken. (For example, your `LANG` environment variable isn't set.) Whatever. – Potatoswatter Apr 29 '10 at 16:08
  • @Potatoswatter: You mean mine *and* `codepad.org`'s platforms are broken. `codepad.org` compiles/runs code on the server side. btw, `LANG` is `en_US.UTF-8` on the machine I've tested. – jfs Apr 29 '10 at 20:25
  • @J.F. http://codepad.org/Adxmw6fC CodePad certainly hasn't set `LANG`, and being an international site, what should their local currency be, anyway? Poor support for this is widespread, but the standard is quite clear about what the output is supposed to look like. – Potatoswatter Apr 29 '10 at 20:31
  • @J.F. What's up with refusing to tell what OS you're using, anyway? That's the only information here that could be useful to anyone. – Potatoswatter Apr 29 '10 at 20:33
  • @Potatoswatter: I don't see how it might help but the platform is `Linux-2.6.32-21-generic-x86_64-with-Ubuntu-10.04-lucid` – jfs Apr 30 '10 at 08:44
  • @J.F.Sebastian What does the following program output in your environment: http://codepad.org/qpFsssWt ? For codepad we can see: `frac_digits: 0` which means the current locale doesn't print any fractional digits and `curr_symbol: ` which means there is no currency symbol defined. This is completely coherent with the given output. – fjardon Aug 28 '13 at 12:03
  • @fjardon: the output is: `moneypunct in locale "en_US.UTF-8": decimal_point: . thousands_sep: , grouping: curr_symbol: $ positive_sign: negative_sign: - frac_digits: 2 1.23` – jfs Aug 29 '13 at 13:16
2
cout << setiosflags(ios::fixed) << setprecision(2) << 1/3.;

ios_base::fixed is not manipulator it is a value (1 << 13) for the ios flag.

jfs
  • 399,953
  • 195
  • 994
  • 1,670