Controlling the amount of decimal places - c++

Is there a way within C++ of setting a definitive amount of decimal points to a float value? for example if i were to record multiple times as float values, i would most likely generate different results (in terms of number of decimal places) and would like to generate numbers of the same lengths i.e if a number were to return as 1.33 and there are other numbers returning as say 1.333 i would like to make the first result read as 1.330.
I understand there are methods of limiting the amount of decimal places such as setprecision() but i do not want to loose accuracy of my times.

You seem to confuse two things: the actual precision of floating point calculations in C++, and formatting of float (or double, or long double) values when printing with C++ streams (like cout, for example).
The first depends on the hardware/platform, and you cannot control it, apart from choosing between float and double. If you need better precision than what long double can give you, you need a library for arbitrary precision maths, for example GMPLIB.
Controlling number of digits after dot when printing/formatting is easier, see for example this question: Set the digits after decimal point

If your need is to limit the digits after the decimal point whether of folat, double or long double then is way is to use (setprecision). When you use it seperately it will be including the digits before decimal point as well and also if the digits after the decimal point are less than the precision being set,it will not add a zero after them. And the solution is to use fixed and showpoint. So if you want to set the precision to 3 digits after the decimal point then write this line before displaying or computing the values.
cout<<fixed<<showpoint<<setprecision(3);

Related

strtof() function misplacing decimal place

I have a string "1613894376.500012077" and I want to use strtof in order to convert to floating point 1613894376.500012077. The problem is when I use strtof I get the following result with the decimal misplaced 1.61389e+09. Please help me determine how to use strof properly.
A typical float is 32-bit and can only represent exactly about 232 different values. "1613894376.500012077" is not one of those.
"1.61389e+09" is the same value as "1613890000.0" and represents a close value that float can represent.
The 2 closest floats are:
1613894272.0
1613894400.0 // slightly closer to 1613894376.500012077
Print with more precision to see more digits.
The decimal point is not misplaced. The notation “1.61389e+09” means 1.61389•109, which is 1,613,890,000., which has the decimal point in the correct place.
The actual result of strtof in your computer is probably 1,613,894,400. This is the closest value to 1613894376.500012077 that the IEEE-754 binary32 (“single”) format can represent, and that is the format commonly used for float. When you print it with %g, the default is to use just six significant digits. To see it with more precision, print it with %.999g.
The number 1613894376.500012077 is equivalent (the same number up to the precision of the machine as 1.61389e+09.) The e+09 suffix means that the decimal point is located nine decimal digits right the place it has been placed (or that the number is multiplied by 10 to the ninth power). This is a common notation in computer science called scientific notation.

C++ set precision of a double (not for output)

Alright so I am trying to truncate actual values from a double with a given number of digits precision (total digits before and after, or without, decimal), not just output them, not just round them. The only built in functions I found for this truncates all decimals, or rounds to given decimal precision.
Other solutions I have found online, can only do it when you know the number of digits before the decimal, or the entire number.
This solution should be dynamic enough to handle any number. I whipped up some code that does the trick below, however I can't shake the feeling there is a better way to do it. Does anyone know of something more elegant? Maybe a built in function that I don't know about?
I should mention the reason for this. There are 3 different sources of observed values. All 3 of these sources agree to some level in precision. Such as below, they all agree within 10 digits.
4659.96751751236
4659.96751721355
4659.96751764253
However I need to only pull from 1 of the sources. So the best approach, is to only use up to the precision all 3 sources agree on. So its not like I am manipulating numbers and then need to truncate precision, they are observed values. The desired result is
4659.967517
double truncate(double num, int digits)
{
// check valid digits
if (digits < 0)
return num;
// create string stream for full precision (string conversion rounds at 10)
ostringstream numO;
// read in number to stream, at 17+ precision things get wonky
numO << setprecision(16) << num;
// convert to string, for character manipulation
string numS = numO.str();
// check if we have a decimal
int decimalIndex = numS.find('.');
// if we have a decimal, erase it for now, logging its position
if(decimalIndex != -1)
numS.erase(decimalIndex, 1);
// make sure our target precision is not higher than current precision
digits = min((int)numS.size(), digits);
// replace unwanted precision with zeroes
numS.replace(digits, numS.size() - digits, numS.size() - digits, '0');
// if we had a decimal, add it back
if (decimalIndex != -1)
numS.insert(numS.begin() + decimalIndex, '.');
return atof(numS.c_str());
}
This will never work since a double is not a decimal type. Truncating what you think are a certain number of decimal digits will merely introduce a new set of joke digits at the end. It could even be pernicious: e.g. 0.125 is an exact double, but neither 0.12 nor 0.13 are.
If you want to work in decimals, then use a decimal type, or a large integral type with a convention that part of it holds a decimal portion.
I disagree with "So the best approach, is to only use up to the precision all 3 sources agree on."
If these are different measurements of a physical quantity, or represent rounding error due to different ways of calculating from measurements, you will get a better estimate of the true value by taking their mean than by forcing the digits they disagree about to any arbitrary value, including zero.
The ultimate justification for taking the mean is the Central Limit Theorem, which suggests treating your measurements as a sample from a normal distribution. If so, the sample mean is the best available estimate of the population mean. Your truncation process will tend to underestimate the actual value.
It is generally better to keep every scrap of information you have through the calculations, and then remember you have limited precision when outputting results.
As well as giving a better estimate, taking the mean of three numbers is an extremely simple calculation.

Conversion from string to double - Possibility and errors

I am aware that the string 2.34 would never be equal to the double 2.34. No matter what library or algorithm you tried (lexical_cast,atof). Also 2.3400 can not be represented as double type. Instead it will be equal to 2.3399999999999999 . A little background I am working on an application that passes of values to an external application using its api. Think of it as some sort of a trading application. The user can pass values using the applications api or the user can pass value by using the application directly.Now when the user uses the application directly and the user types in 2.34 the value is processed as 2.34 however when I use the API which requires double as a parameter I pass 2.34 and it passes of as 2.3399999999999999 which is not acceptable. My question is how would the application be handling this and is there a way to store 2.34000.. in a double so that I could pass it to an API ?
If you need to pass decimal values through an API which takes double but you need to get the exact values, there isn't much of a problem: As long as you don't use more than std::numeric_limits<double>::digits10 digits, you can recover the original decimal value although not necessarily the same representation (trailing fractional zeros will be lost). To do so, you need to convert the original decimal string into the closest representation as double and later use a suitable algorithm to restore the best decimal representation again. The parsing and formatting functions from the C and C++ standard libraries will do that correctly for you.
Note that you shouldn't try to do any arithmetic on the double values when you want to restore the original decimal values: the result of double arithmetic will use binary rounding and the values won't be the closest decimal values. However, as long as you only transfer the double values, there is no problem.
Since you mention "trading application" I will conclude that the numbers represent currencies. If that is the case you are probably dealing with a fixed number of fractional digits as well. In that case you can scale your floating point numbers by multiplying them by 10 ^ number_of_fractional_digits, essentially making them integer values. Floating point numbers can accurately store integer values (as long as they do not exceed the floating point type's range).
Another possibility - if the assumptions above are correct - would be to use Binary-coded decimals.
The one way to work around floating point precision issues is using a well made fraction class. You may code one for yourself or use the ones provided by common math libraries. Such classes will represent your 2.34 as 234/100 internally, which will lead higher amount of memory consumption compared to a single float.

Rounding problem with double type [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Why don't operations on double-precision values give expected results?
I am experiencing a peculiar problem in C++. I created a variable of type Double. Then I did some calculations with some values assigned to other variables and assigned the result to the double variable I declared. It gave me a result with a long decimal part. I want it to round to only 2 decimal places. and store it into the variable. But even after several attempt rounding, I couldnt round it to 2 decimal places.
Then I tried another way to check what the real problem is. I created a Double variable and assigned it the value 1.11. But when I debugged it by putting a break point and added a watch for that variable, I could find that the value now stored in the variable is 1.109999999999.
My question is, why is it showing like that? Isnt there any way in which we can round the variable into two decimal places? Why is it showing a long decimal part even if we assign a number with just two decimal places?
Please suggest a way to store numbers - whether it is calculated or directly assigned - as it is, in a double variable rather than a number with a long decimal part.
In the set of double values, there is no such thing as the number 1.11 because internally, double uses a binary representation (as opposed to humans who are used to a decimal representation). Most finite decimal numbers (such as 1.11) have an infinite representation in binary, but since memory is limited, you lose some precision because of rounding.
The closest you can get to 1.11 with the double data type is 1.1100000000000000976996261670137755572795867919921875, which is internally represented as 0x3ff1c28f5c28f5c3.
Your requirement of two decimal places sounds like you are working with money. A simple solution is to store the cents in an integer (as opposed to the dollars in a double):
int cents = 111;
This way, you don't lose any precision. Another solution is to use a dedicated decimal data type.
the floating-point types like float and double are not 100% precise. They may store 14.3 as 14.299999... and there is nothing wrong about that. That is why you should NEVER compare two floats or doubles with == operator, instread you should check if the absolute value of their difference is smaller than a certain epsilon, like 0.000000001
Now, if you want to output the number in a pleasant way, you can use setprecision from <iomanip>
E.g.
#include <iostream>
#include <iomanip>
int main()
{
double d = 1.389040598345;
std::cout << setprecision(2) << d; //outputs 1.39
}
If you want to obtain the value of d rounded 2 decimal places after the point, then you can use this formula
d = floor((d*100)+0.5)/100.0; //d is now 1.39
Not every decimal number has an exact, finite, binary floating-point representation. You've already found one example, but another one is 0.1 (decimal) = 0.0001100110011... (binary).
You either need to live with that, or use a decimal floating-point library (which will be less efficient).
My recommendation would be to store numbers to full precision, and only round when you need to display them to humans.

Setprecision() for a float number in C++?

In C++,
What are the random digits that are displayed after giving setprecision() for a floating point number?
Note: After setting the fixed flag.
example:
float f1=3.14;
cout < < fixed<<setprecision(10)<<f1<<endl;
we get random numbers for the remaining 7 digits? But it is not the same case in double.
Two things to be aware of:
floats are stored in binary.
float has a maximum of 24 significant bits. This is equivalent to 7.22 significant digits.
So, to your computer, there's no such number as 3.14. The closest you can get using float is 3.1400001049041748046875.
double has 53 significant bits (~15.95 significant digits), so you get a more accurate approximation, 3.140000000000000124344978758017532527446746826171875. The "noise" digits don't show up with setprecision(10), but would with setprecision(17) or higher.
They're not really "random" -- they're the (best available) decimal representation of that binary fraction (will be exact only for fractions whose denominator is a power of two, e.g., 3.125 would display exactly).
Of course that changes depending on the number of bits available to represent the binary fraction that best approaches the decimal one you originally entered as a literal, i.e., single vs double precision floats.
Not really a C++ specific issue (applies to all languages using binary floats, typically to exploit the machine's underlying HW, i.e., most languages). For a very bare-bone tutorial, I recommend reading this.