Store float with exactly 2 decimal places in C++ - c++

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++?

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.

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.

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/

Related

Implicit conversion from long long to float yields unexpected result

In an attempt to verify (using VS2012) a book's claim (2nd sentence) that
When we assign an integral value to an object of floating-point type, the fractional part is zero.
Precision may be lost if the integer has more bits than the floating-point object can accommodate.
I wrote the following wee prog:
#include <iostream>
#include <iomanip>
using std::cout;
using std::setprecision;
int main()
{
long long i = 4611686018427387905; // 2^62 + 2^0
float f = i;
std::streamsize prec = cout.precision();
cout << i << " " << setprecision(20) << f << setprecision(prec) << std::endl;
return 0;
}
The output is
4611686018427387905 4611686018427387900
I expected output of the form
4611686018427387905 4611690000000000000
How is a 4-byte float able to retain so much info about an 8-byte integer? Is there a value for i that actually demonstrates the claim?
Floats don't store their data in base 10, they store it in base 2. Thus, 4611690000000000000 isn't actually a very round number. It's binary representation is:
100000000000000000000111001111100001000001110001010000000000000.
As you can see, that would take a lot of data to precisely record. The number that's actually printed, however, has the following binary representation:
11111111111111111111111111111111111111111111111111111111111100
As you can see, that's a much rounder number, and the fact that it's off by 4 from a power of two is likely due to rounding in the convert-to-base-10 algorithm.
As an example of a number that won't fit in a float properly, try the number you expected:
4611690000000000000
You'll notice that that will come out very differently.
The float retains so much information because you're working with a number that is so close to a power of 2.
The float format stores numbers in basically binary scientific notation. In your case, it gets stored as something like
1.0000000...[61 zeroes]...00000001 * 2^62.
The float format can't store 62 decimal places, so the final 1 gets cut off... but we're left with 2^62, which is almost exactly equal to the number you're trying to store.
I'm bad at manufacturing examples, but CERT isn't; you can view an example of what happens with bungled number conversions here. Note that the example is in Java, but C++ uses the same floating point types; additionally, the first example is a conversion between a 4-byte int and a 4-byte float, but this further proves your point (there's less integer information that needs to be stored than there is in your example, yet it still fails).

Does insertion and extraction of a floating point number to some of the standard stream classes preserves its value?

When I debug I sometimes want to print the floating point number returned by a function and use it as an input value for another function. I wonder what are the default parameters which guide the formatting of the floating point numbers.
Are f1 and f2 always the same in the following code?
#include <sstream>
#include <cassert>
int main(int argc, const char *argv[])
{
std::stringstream ss;
float f1 = .1f;
ss << f1;
float f2;
ss >> f2;
assert(f1 == f2);
return 0;
}
Can I write a bunch of floating point numbers to std::cout or std::ofsteam and read them back to get exactly the same numbers or should I explicitly set the amount of numbers after the decimal mark (like it is suggested here?
What bothers me is that although .1 is not representable as a binary fraction it is still formatted correctly by the standard streams.
Not necessarily. By default, ostream outputs 6 digits of
precision. To be able to "round trip" a float, you need
a precision of std::numeric_limits<float>::max_digits10 (which
is 9 for the most common representation). If the stream is
being used for persistance, and you're only persisting floats,
just set the precision before writing anything, e.g.:
ss.precision( std::numeric_limits<float>::max_digits10 );
(If you need to handle both float and double, and don't want
the extra digits on float, you'll need to set the precision
each time you output a floating point value.)
No, they're not guaranteed to be the same.
What's happening is that the float itself has more precision than it'll print out as by default, so as long as what you read in has fewer significant digits than the default output precision, what you print out will (at least usually) be rounded back to the value you read in.
If, however, you have data that uses the full precision of your float, and you read it in and then write it back out at full precision, you'll start to see differences.
#include <sstream>
#include <iomanip>
#include <iostream>
int main() {
std::istringstream buffer("0.1");
float value;
buffer >> value;
std::cout << value << "\n";
std::cout << std::setprecision(10) << value;
}
Result:
0.1
0.1000000015
In this case, the trailing 15 is (approximately) the difference between 0.1 and the closest approximation to it that my compiler's float can represent.
Even more important, assert(f1 == f2); when f1 and f2 are both floating point numbers is rarely correct. You want something like assert(abs(f1 - f2) < tolerance); There are several techniques commonly used for choosing tolerance. Which one you should use depends on the problem your program is addressing.

How to use set up decimal precision for all double type numbers in a large C++ program

How to use set up decimal precision for all double type numbers in a large C++ program.
I can use stringstream and setprecision(n) to do it but I have to do it one by one for every double number in the whole program.
How to do it globally once for all so that all double type numbers in the program has fixed decimal digits after decimal point (e.g. 4) ?
I do not want to use function call to cause calling overhead.
thanks
double type is not designed to do what you want: it is a floating decimal type, not a fixed decimal type. What you need is some kind of decimal type, but unfortunately C++ does not yet have such type.
It can be emulated most of the times with an integer type where you assume that it represents the then-thousandths of a unit. You just have to be careful in the multiplications and divisions to fix the scale. Additions and subtractions work automatically.
setprecision does not change the precision of double values, but just the precision used when converted into a string.
And converting doubles into strings is relatively expensive operation, so the overhead of a single extra function call should be negligible. If you use double-string conversion in performance critical code, then you are doing it wrong.
My advice would be to just write a function such as:
std::string FmtDbl(double d)
{
std::ostringstream os;
os << std::setprecision(4) << d;
return os.str();
}
And use that function everywhere you need the conversion.

Converting variable type (or workaround)

The class below is supposed to represent a musical note. I want to be able to store the length of the note (e.g. 1/2 note, 1/4 note, 3/8 note, etc.) using only integers. However, I also want to be able to store the length using a floating point number for the rare case that I deal with notes of irregular lengths.
class note{
string tone;
int length_numerator;
int length_denominator;
public:
set_length(int numerator, int denominator){
length_numerator=numerator;
length_denominator=denominator;
}
set_length(double d){
length_numerator=d; // unfortunately truncates everything past decimal point
length_denominator=1;
}
}
The reason it is important for me to be able to use integers rather than doubles to store the length is that in my past experience with floating point numbers, sometimes the values are unexpectedly inaccurate. For example, a number that is supposed to be 16 occasionally gets mysteriously stored as 16.0000000001 or 15.99999999999 (usually after enduring some operations) with floating point, and this could cause problems when testing for equality (because 16!=15.99999999999).
Is it possible to convert a variable from int to double (the variable, not just its value)? If not, then what else can I do to be able to store the note's length using either an integer or a double, depending on the what I need the type to be?
If your only problem is comparing floats for equality, then I'd say to use floats, but read "Comparing floating point numbers" / Bruce Dawson first. It's not long, and it explains how to compare two floating numbers correctly (by checking the absolute and relative difference).
When you have more time, you should also look at "What Every Computer Scientist Should Know About Floating Point Arithmetic" to understand why 16 occasionally gets "mysteriously" stored as 16.0000000001 or 15.99999999999.
Attempts to use integers for rational numbers (or for fixed point arithmetic) are rarely as simple as they look.
I see several possible solutions: the first is just to use double. It's
true that extended computations may result in inaccurate results, but in
this case, your divisors are normally powers of 2, which will give exact
results (at least on all of the machines I've seen); you only risk
running into problems when dividing by some unusual value (which is the
case where you'll have to use double anyway).
You could also scale the results, e.g. representing the notes as
multiples of, say 64th notes. This will mean that most values will be
small integers, which are guaranteed exact in double (again, at least
in the usual representations). A number that is supposed to be 16 does
not get stored as 16.000000001 or 15.99999999 (but a number that is
supposed to be .16 might get stored as .1600000001 or .1599999999).
Before the appearance of long long, decimal arithmetic classes often
used double as a 52 bit integral type, ensuring at each step that the
actual value was exactly an integer. (Only division might cause a problem.)
Or you could use some sort of class representing rational numbers.
(Boost has one, for example, and I'm sure there are others.) This would
allow any strange values (5th notes, anyone?) to remain exact; it could
also be advantageous for human readable output, e.g. you could test the
denominator, and then output something like "3 quarter notes", or the
like. Even something like "a 3/4 note" would be more readable to a
musician than "a .75 note".
It is not possible to convert a variable from int to double, it is possible to convert a value from int to double. I'm not completely certain which you are asking for but maybe you are looking for a union
union DoubleOrInt
{
double d;
int i;
};
DoubleOrInt length_numerator;
DoubleOrInt length_denominator;
Then you can write
set_length(int numerator, int denominator){
length_numerator.i=numerator;
length_denominator.i=denominator;
}
set_length(double d){
length_numerator.d=d;
length_denominator.d=1.0;
}
The problem with this approach is that you absolutely must keep track of whether you are currently storing ints or doubles in your unions. Bad things will happen if you store an int and then try to access it as a double. Preferrably you would do this inside your class.
This is normal behavior for floating point variables. They are always rounded and the last digits may change valued depending on the operations you do. I suggest reading on floating points somewhere (e.g. http://floating-point-gui.de/) - especially about comparing fp values.
I normally subtract them, take the absolute value and compare this against an epsilon, e.g. if (abs(x-y)
Given you have a set_length(double d), my guess is that you actually need doubles. Note that the conversion from double to a fraction of integer is fragile and complexe, and will most probably not solve your equality problems (is 0.24999999 equal to 1/4 ?). It would be better for you to either choose to always use fractions, or always doubles. Then, just learn how to use them. I must say, for music, it make sense to have fractions as it is even how notes are being described.
If it were me, I would just use an enum. To turn something into a note would be pretty simple using this system also. Here's a way you could do it:
class Note {
public:
enum Type {
// In this case, 16 represents a whole note, but it could be larger
// if demisemiquavers were used or something.
Semiquaver = 1,
Quaver = 2,
Crotchet = 4,
Minim = 8,
Semibreve = 16
};
static float GetNoteLength(const Type &note)
{ return static_cast<float>(note)/16.0f; }
static float TieNotes(const Type &note1, const Type &note2)
{ return GetNoteLength(note1)+GetNoteLength(note2); }
};
int main()
{
// Make a semiquaver
Note::Type sq = Note::Semiquaver;
// Make a quaver
Note::Type q = Note::Quaver;
// Dot it with the semiquaver from before
float dottedQuaver = Note::TieNotes(sq, q);
std::cout << "Semiquaver is equivalent to: " << Note::GetNoteLength(sq) << " beats\n";
std::cout << "Dotted quaver is equivalent to: " << dottedQuaver << " beats\n";
return 0;
}
Those 'Irregular' notes you speak of can be retrieved using TieNotes

Fixed Length Float in C/C++?

I was wondering whether it is possible to limit the number of characters we enter in a float.
I couldn't seem to find any method. I have to read in data from an external interface which sends float data of the form xx.xx. As of now I am using conversion to char and vice-versa, which is a messy work-around. Can someone suggest inputs to improve the solution?
If you always have/want only 2 decimal places for your numbers, and absolute size is not such a big issue, why not work internally with integers instead, but having their meaning be "100th of the target unit". At the end you just need to convert them back to a float and divide by 100.0 and you're back to what you want.
This is a slight misunderstanding. You cannot think of a float or double as being a decimal number.
Most any attempt to use it as a fixed decimal number of precision, say, 2, will incur problems as some values will not be precisely equal to xxx.xx but only approximately so.
One solution that many apps use is to ensure that:
1) display of floating point numbers is well controlled using printf/sprintf to a certain number of significant digits,
2) one does not do exact comparison between floating point numbers, i.e. to compare to the 2nd decimal point of precision two numbers a, b : abs(a-b) <= epsilon should generally be used. Outright equality is dangerous as 0.01 might have multiple floating point values, e.g. 0.0101 and 0.0103 might result if you do arithmetic, but be indistinguishable to the user if values are truncated to 2 dp, and they may be logically equivalent to your application which is assuming 2dp precision.
Lastly, I would suggest you use double instead of float. These days there is no real overhead as we aren't doing floating point without a maths coprocessor any more! And a float under 32-bit architectures has 7 decimal points of precision, and a double has 15, and this is enough to be significant in many case.
Rounding a float (that is, binary floating-point number) to 2 decimal digits doesn't make much sense because you won't be able to round it exactly in some cases anyway, so you'll still get a small delta which will affect subsequent calculations. If you really need it to be precisely 2 places, then you need to use decimal arithmetic; for example, using IBM's decNumber++ library, which implements ISO C/C++ TR 24773 draft
You can limit the number of significant numbers to output:
http://www.cplusplus.com/reference/iostream/manipulators/setprecision/
but I don't think there is a function to actually lop off a certain number of digits. You could write a function using ftoa() (or stringstream), lop off a certain number of digits, and use atof() (or stringstream) and return that.
You should checks the string rather than the converted float. It will be easier to check the number of digits.
Why don't you just round the floats to the desired precision?
double round(double val, int decimalPlaces)
{
double power_of_10 = pow(10.0, static_cast<double>(decimalPlaces));
return floor(val * power_of_10 + 0.5) / power_of_10;
}
int main()
{
double d;
cin >> d;
// round d to 3 decimal places...
d = round(d, 3);
// do something with d
d *= 1.75;
cout << setprecision(3) << d; // now output to 3 decimal places
}
There exist no fixed point decimal datatype in C, but you can mimic pascal's decimal with a struct of two ints.
If the need is to take 5 digits [ including or excluding the decimal point ], you could simply write like below.
scanf( "%5f", &a );
where a is declared as float.
Fo eg:
If you enter 123.45, scanf will consider the first 5 characters i.e., 4 digits and the decimal point & will store 123.4
If entered 123456, the value of a will be 12345 [ ~ 12345.00 ]
With printf, we would be able to control how many characters can be printed after decimal as well.
printf( "%5.2f \n", a );
The value of 123.4 will be printed as 12.30 [ total 5, including the decimal & 2 digits after decimal ]
But this have a limitation, where if the digits in the value are more than 5, it will display the actual value.
eg: The value of 123456.7, will be displayed as 123456.70.
This [ specifying the no. of digits after the decimal, as mentioned for printf ] I heard can be used for scanf as well, I am not sure sure & the compiler I use doesn't support that format. Verify whether your compiler does.
Now, when it comes to taking data from an external interface, are you talking about serialization here, I mean transmission of data on netwrok.
Then, to my knowledge your approach is fine.
We generally tend to read in the form of char only, to make sure the application works for any format of data.
You can print a float use with printf("%.2f", float), or something similar.