1

I would like to take a decimal or non-decimal value and store it as a string with exactly 2 decimal places in C++. I want to do this to show it as a monetary value, so it is always $10.50 or $10.00 rather than $10.5 or $10.

I don't just want to print this, I want to store it, so I don't believe setprecision will work here. I'm doing this in a Qt application, so if there is a way to do it using Qt I can use that as well.

For example:

int cents = 1000;
std::string dollars; //should get value from cents formatted to 10.00

UPDATE: It seems I don't have the vocabulary yet as I am just beginning to learn C++ to articulate what I am trying to do. Here is what I want to do using Python:

str_money = '$ {:.2f}'.format(num)

In this example, num can be a decimal or not (10 or 10.5 for example) and str_money is a variable that is assigned the value of num as a decimal with exactly 2 numbers after the decimal (in this example, str_money would become 10.00 or 10.50). I want it to store this in a string variable, and I don't need it to store the '$' with the value.

Can I do this in C++?

Ricky Kresslein
  • 372
  • 1
  • 13
  • 1
    What do you mean with 'store' - do you want to display it or write it to a file or something else? – chehrlic Jan 08 '22 at 14:02
  • 2
    If you want to actually store it, it might be better to just use an integer type, then `/100.` when you need to print it – Ranoiaetep Jan 08 '22 at 14:03
  • 4
    `float` is a binary number there is no way to store with a specific number of decimal places as `float` can only approximate decimal values. Money is normally handled with integers, in your case just store the number of cents in an `int` instead of dollars in `float`. see https://stackoverflow.com/questions/588004/is-floating-point-math-broken – Alan Birtles Jan 08 '22 at 14:04
  • This is not possible due to how a IEEE-754 floating point number works in your CPU. See here for a calculator that shows how a floating point number is represented: [https://h-schmidt.net/FloatConverter/](https://h-schmidt.net/FloatConverter/) – drescherjm Jan 08 '22 at 14:25
  • 1
    Multiply the values by 100 and store in an integer type. – Pete Becker Jan 08 '22 at 14:28
  • For money its recommended to set the unit to cents and operate using integers. – drescherjm Jan 08 '22 at 14:47
  • 2
    Use fixed point arithmetic for currencies. Tom scott discusses this exact topic here (its light viewing and might really help you): Floating point numbers computerphile https://www.youtube.com/watch?v=PZRI1IfStY0 – Pepijn Kramer Jan 08 '22 at 14:51
  • I've updated the question to better articulate what I am trying to do. – Ricky Kresslein Jan 08 '22 at 15:49

3 Answers3

3

Your decision to store monetary amounts as integer number of cents is a wise one, because floating-point data types (such as float or double) are generally deemed unsuitable for dealing with money.

Also, you were almost there by finding std::setprecision. However, it needs to be combined with std::fixed to have the expected effect (because std::setprecision means different things depending on which format option is used: the default, scientific or fixed).

Finally, to store the formatting result in an std::string instead of directly printing it to the console, you can use a string-based output stream std::ostringstream. Here is an example:

#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

std::string cents_to_dollars_string(const int cents)
{
    static constexpr double cents_per_dollar{ 100. };
    static constexpr int decimal_places{ 2 };

    std::ostringstream oss;
    oss << std::fixed << std::setprecision(decimal_places) << cents / cents_per_dollar;
    return oss.str();
}

int main()
{
    const int balance_in_cents{ -420 };
    const std::string balance_in_dollars{ cents_to_dollars_string(balance_in_cents) };
    std::cout << "Your balance is " << balance_in_dollars << '\n';
}

Here, we first define the function cents_to_dollars_string, which takes the amount in cents as an int and returns an std::string containing the formatted amount of dollars. Then, in main we call this function to convert an amount (in cents) stored in an int variable balance_in_cents to a string and store it into an std::string variable balance_in_dollars. Finally, we print the balance_in_dollars variable to the console.

heap underrun
  • 1,846
  • 1
  • 18
  • 22
1

If you want to store a fixed number of decimal places, a float is not what you want. You want a fixed-point number. With money, the basic idea is to store the value as "cents" in an integer. Then you can perform a division by 100 whenever you want to output the value as "dollars". (Or have a custom output function or operator that formats the output correctly.)

One of the big benefits to fixed-point arithmetic is that you can avoid rounding errors. Floating point numbers are really bad at exactly storing decimal fractions, so dealing with "tenths" or "hundredths" can easily result in rounding errors that can add up in long running, or complicated programs.

How you implement your fixed point numbers is largely up to you. You might find a library that has a fixed-point class, you could implement your own, or you could just manipulate integer variables.

Kyle A
  • 928
  • 7
  • 17
  • If I store the number as an int and divide by 100 when it is displayed then it does not show two decimal places, only 0 or 1. For example, 850 cents / 100 would be 8.5. I want it to show as 8.50. Is there a way to do this? – Ricky Kresslein Jan 08 '22 at 18:46
  • 2
    @RickyKresslein yes, just set the precision when doing your string conversion (or more simply just convert the integer to string and insert the decimal point as the 3rd last character) – Alan Birtles Jan 09 '22 at 06:56
0

If you want this happen on output then you can use setprecision () method as it sets the decimal precision to be used to format floating-point values on output operations.

find more https://www.cplusplus.com/reference/iomanip/setprecision/#:~:text=std%3A%3Asetprecision&text=Sets%20the%20decimal%20precision%20to,input%20streams%20or%20output%20streams).

and check this solution for the problem

https://www.geeksforgeeks.org/rounding-floating-point-number-two-decimal-places-c-c/

  • This is almost what I want to do, but instead of outputting the number I want to assign it to a string variable. – Ricky Kresslein Jan 08 '22 at 18:43
  • When you want to use Qt see [QString::number()](https://doc.qt.io/qt-5/qstring.html#number-6) – chehrlic Jan 08 '22 at 21:02
  • @chehrlic Yes, I'm using QString::number() to change the number to a QString. But that does not resolve the issue of adding two decimal places. – Ricky Kresslein Jan 08 '22 at 21:16
  • Then use QString::setNum() or QString::arg() - wonder why reading a documentation is so hard. esp. when QString::number() already points to the related functions I mentioned... – chehrlic Jan 09 '22 at 09:33