I am currently working a program where I need to calculate a rounded value to only 2 digits after a floating point.
Say, I have declared
float a;
If a = 3.555 then it would store a = 3.56, rounding up.
For a = 3.423, the value of a would be a = 3.423, no change.
I can do this to print output, but what I need to do when storing it into a variable and use that variable for some other calculation?
If you need two digits after the decimal point, don't use floating point. Use a fixed point number instead. For example, just use an integer that's 100 times larger than the decimal number you want to represent. Trying to fit a base 2 floating point number into rounding rules like this just isn't going to produce satisfactory results for you.
double d = 5000.23423;
d = ceil(d*100)/100;
cout << d << endl; // prints : 5000.24
double e = 5000.23423;
e = floor(e*100)/100;
cout << e << endl; // prints : 5000.23
You can do this:
a = roundf(a*100)/100;
How about
#include <math.h>
int main ()
{
double a, f, i;
a = 3.436;
f= modf(a, &i);
a = i + roundf(f* 100.0) / 100.0;
return 0;
}
Operates on doubles but avoids scaling the whole number.
Update: Added the missing division.
Related
I know that we shouldn't use floating points in the loops. But could someone explain it to me what happens when we have a loop and we add a small number to a large number until we reach a certain value that allows the loop to terminate?
I guess it might cause potential errors. But apart from that?
What would it look like with a single-precision (float) and double-precision (double) floating-point numbers? I guess more rounding errors would appear in the double type. Could someone give me an example (the best in C ++) because I have no idea how to start with it...
I would be very grateful if you could provide me with a hint. Thanks!
In a C++ implementation using IEEE-754 arithmetic and the “single” (binary32) format for float, this code prints “count = 3”:
int count = 0;
for (float f = 0; f < .3f; f += .1f)
++count;
std::cout << "count = " << count << ".\n";
but this code prints “count = 4”:
int count = 0;
for (float f = 0; f < .33f; f += .11f)
++count;
std::cout << "count = " << count << ".\n";
In the first example, the source text .1f is converted to 0.100000001490116119384765625, which is the value representable in float that is closed to .1. The source text .3f is converted to 0.300000011920928955078125, the float value closest to .3. Adding this converted value for .1f to f produces 0.100000001490116119384765625, then 0.20000000298023223876953125, and then 0.300000011920928955078125, at which point f < .3f is false, and the loop stops.
In the second example, .11f is converted to 0.10999999940395355224609375, and .33f is converted to 0.3300000131130218505859375. In this case, adding the converted value of .11f to f produces 0.10999999940395355224609375, then 0.2199999988079071044921875, and then 0.329999983310699462890625. Note that, due to rounding, this result of adding .11f three times is 0.329999983310699462890625, which is less than .33f (0.3300000131130218505859375), so f < .33f is true, and the loop continues for another iteration.
This is similar to adding ⅓ in a two-digit decimal format with a loop bound of three-thirds (which is 1). If we had for (f = 0; f < 1; f += ⅓), the ⅓ in the source text would have to be converted to .33 (two-digit decimal). Then f would be stepped through .33, .66, and .99. The loop would not stop until it reached 1.32. The same rounding issues occur in binary floating-point arithmetic.
When the amount added in the loop is a small number relative to the large number, these rounding issues are greater. First, there will be more additions, so there will be more rounding errors, and they may accumulate. Second, since larger numbers require a larger exponent to scale them in the floating-point format, they have less absolute precision than smaller numbers. This means the roundings have to be come larger relative to the small number that is being added. So the rounding errors are larger in magnitude.
Then, even if the loop eventually terminates, the values of f in each iteration may be far from the desired values, due to the accumulated errors. If f is used for calculations inside the loop, the calculations might not be using the desired values and may produce incorrect results.
With increasing values the difference between 2 floating point values increases too. There is a point where i+1 results in the same value.
Consider this code:
#include <iostream>
int main()
{
float i = 0;
while (i != i + 1) i++;
std::cout << i << std::endl;
return 0;
}
while (i != i + 1) should be an endless loop, but for floating point variables, it is not.
The code above prints 1.67772e+07 on https://godbolt.org/z/7xf8n8
So, for (float f = 0; f < 2e7; f++) is an endless loop.
You can try it with double yourself, the value is bigger.
Is there any way to determine how many numbers are there in my double after decimal point. for example double a=3.14259
If I make a new int b now, how can I make value of bequal to numbers after decimal point from a?
The short answer is, you can't.
first of all, a type like double has always the same number of binary digits after a (binary) period. That is called mantissa. in case of double that are 53 bits, meaning 52 bit after binary period, in decimal that are about 15 digits. For details you may have a look a IEEE_754 (double precision)
When you convert a double to a decimal string, you will in general never match exact decimal. For example the value 0.1 could not exactly represented by a double value. a printf may show "0.1" after applying rounding.
However, when you are dealing with some double calculations you will experience small deriviation like 0.10000000000012 or 0.09999999999987. What will you do in such cases?
And there is a mathematican problem which has nothing to do with c++ doubles:
_
0.1 is equal to 0.09
so your answer would either 1 or infinity
Here is one way to do it: Convert the decimal to a string, and find the size of the substring after the decimal point, as follows:
#include <iostream>
#include <string>
int main()
{
double a = 3.14259;
std::string a_string = std::to_string(a);
a_string.erase ( a_string.find_last_not_of('0') + 1, std::string::npos ); //Get rid
//of extra zeroes
std::cout << a_string.substr(a_string.find('.') + 1).size() << "\n";
//Print the size of the substring of the original string from the decimal point (here 5)
}
You could treat the fractional part as a string literal. Utilize the std::stringstream and std::string:
#include <iostream>
#include <string>
#include <sstream>
int main(){
double whole = 3.14259;
auto fractionalno = whole - static_cast<long>(whole); // or use std::modf()
std::stringstream ss;
ss << fractionalno;
std::string s = ss.str();
s.erase(0,2);
std::cout << "The number of digits is: " << s.size();
}
Floating point number does not provide the number of digits after the point. (It is not even the 'exact' value. It is an approximate value.)
But if you just want to make another integer to have the same number of digits after the point just on the screen, why don't you just count?
Here is Python code:
a = 4.0 / 7
# a is 0.5714285714285714
b = str(a)
# b (str(a)) is 0.571428571429, different with a.
nod = len(b[b.index('.'):])
_c = 9.0 / 7
c = float(int(_c * 10 ** nod)) / 10 ** nod
This question already has answers here:
C++ program converts fahrenheit to celsius
(8 answers)
Closed 7 years ago.
First of all, I want to say sorry because I think the doubt is so trivial... but I'm new programming in C++.
I have the following code:
int a = 234;
int b = 16;
float c = b/a;
I want to print the result from float c with 2 decimals (the result should be 0.06) but I don't get the expected result.
Can anyone can help me? I tried using CvRound() and setPrecision() but nothing works like I expect or, in my case, I don't know how to do them working.
The problem is actually blindingly simple. And has NOTHING whatsoever do do with settings such as precision.
a and b are of type int, so b/a is also computed to be of type int. Which involves rounding toward zero. For your values, the result will be zero. That value is then converted to be float. An int with value zero, when converted to float, gives a result of 0.0. No matter what precision you use to output that, it will still output a zero value.
To change that behaviour convert one of the values to float BEFORE doing the division.
float c = b/(float)a;
or
float c = (float)b/a;
The compiler, when it sees a float and and an int both participating in a division, converts the int to float first, then does a division of floats.
int a = 234;
int b = 16;
float c = b/(float)a;
float rounded_down = floorf(c * 100) / 100; /* floor value upto two decimal places */
float nearest = roundf(c * 100) / 100; /* round value upto two decimal places */
float rounded_up = ceilf(c * 100) / 100; /* ceiling value upto two decimal places */
If you just want to print the result, you can use a printf() formatting string to round:
printf("c = %.2f\n", number, pointer);
Otherwise, if you need c to calculate another value, you shouldn't round the original value, only the one to print.
try this:
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
int a = 234;
int b = 16;
float c = float(b)/a;
cout<<fixed<<setprecision(2)<<c;
return 0;
}
Previously when c = b/a since a and b are integers so by integer division we were getting answer as 0 as per your program.
But if we typecast one of the variable(a or b) to float we will obtain decimal answer.
Number of digits after decimal may or may not be 2. To ensure this we can use fixed and setprecision. fixed will ensure that number of digits after decimal will be fixed. setprecision will set how many digits to be there after decimal.
This question already has answers here:
Precision loss with double C++
(4 answers)
Closed 9 years ago.
So I have the following code
int main(){
double d;
cin>>d;
while(d!=0.00)
{
cout<<d<<endl;
double m = 100*d;
int n = m;
cout<<n<<endl;
cin>>d;
}
return 0;}
When I enter the input 20.40 for d the value of n comes out to be 2039 instead of 2040.
I tried replacing int n = m with int n = (int) m but the result was the same.
Is there any way to fix this. Thanks in advance.
Your code truncates m but you need rounding. Include cmath and use int n = round(m).
Decimal values can, in general, not be represented exactly using binary floating points like double. Thus, the value 20.40 is represented as an approximation which can be used to restore the original value (20.4; the precision cannot be retained), e.g., when formatting the value. Doing computations with these approximated values will typically amplify the error.
As already mentioned in one of the comments, the relevant reference is the paper "What Every Computer Scientist Should Know About Floating-Point Arithmetic". One potential way out of your trouble is to use decimal floating points which are, however, not yet part of the C++ standard.
Single and double presicion floating point numbers are not stored the same way as integers, so whole numbers (e.g. 5, 10) may actually look like long decimals (e.g. 4.9999001, 10.000000001). When you cast to an int, all it does is truncate the whole number. So, if the number is currently represented as 4.999999999, casting it to an int will give you 4. std::round will provide you with a better result most of the time (if the number is 4.6 and you just want the whole number portion, round will not work well). The bigger question is then: what are you hoping to accomplish by casting a double to an int?
In general, when dealing with floating point numbers, you will want to use some epsilon value that is your minimum significant digits. So if you wanted to compare 4.9999999 to 5, you would do (pseudo-code): if abs(5 - 4.9999999) < epsilon, return 5.
Example
int main()
{
double d;
std::cin >> d;
while (std::fabs(d - 0.0) > DBL_EPSILON)
{
std::cout << d << std::endl;
double m = 100 * d;
int n = static_cast<int>(m);
if (std::fabs(static_cast<double>(n) - m) > DBL_EPSILON)
{
n++;
}
std::cout << n << std::endl;
std::cin >> d;
}
return 0;
}
Casting double to int truncates value so 20.40 is probably 20.399999 * 100 is 2039.99 because double is not base 10. You can use round() function that will not truncate but will get you nearest int.
int n = round(m);
Floating point numbers can't exactly represent all decimal numbers, sometimes an approximation is used. In your example the closest possible exact number is 20.39999999999999857891452847979962825775146484375. See IEEE-754 Analysis for a quick way to see exact values.
You can use rounding, but presumably you're really looking for the first two digits truncated. Just add a really small value, e.g. 0.0000000001 before or after you multiply.
How can I do math involving significant figures in C++? I want this to work correct with measured data from chemistry and physics experiments. An example: 65 / 5 = 10. I would need to get rid of unneeded decimal places and replace some digits with 0s.
Thanks!
This should get you what you need:
std::cout.precision(x); // x would be the number of significant figures to output
This may not be the most efficient way, but you can create a custom sig fig data type.
class SigFigFloat
{
SigFigFloat(vector<short> digits, int decimalIndex, bool negative);
SigFigFloat operator+(const SigFigFloat &value);
SigFigFloat operator-(const SigFigFloat &value);
//etc...
}
It can be a lot of work, but if you implement this right, it can be a really flexible way to represent and do calculations with sig figs.
It is hard because significant figures are a decimal concept, and computers speak binary. You can use decimal number classes (I don't know of any), or use boost::interval, which is the closest to what you certainly want to achieve.
That depends on how you are displaying them. If you are using the printf-family, you set the precision (sprintf(buffer, "%.2f", myfloat)). If you are using ostreams, you call the precision function to set the number of decimal places. If you are looking for the more scientific method of sig figs, you'll have to write a custom function that determines the precision based on the current value of the float.
You can also:
#define SIGNIFICANT_DIGITS 3
const float SIGNIFICANT_DIGITS_PWR = powf(10.0f, SIGNIFICANT_DIGITS);
float f;
std::cin >> f;
int int_digits = (int)log10f(f) + 1;
if (int_digits > 1) {
float prod = SIGNIFICANT_DIGITS_PWR / powf(10.0f, int_digits);
f = (float)(int)(f * prod) / prod;
} else {
f = (float)((int)(f * SIGNIFICANT_DIGITS_PWR)) / SIGNIFICANT_DIGITS_PWR;
};
std::cout << f << '\n';
Output:
0.1234
> 0.123
12.34
> 12.3
1234
> 1230
here is a quick C++11 solution that worked for me:
int sig_figs = 3;
double number = 1562.654478;
std::cout << "original number:" << number << std::endl;
number = ([number](int number_of_sig_figs)->double{
std::stringstream lStream;
lStream << std::setprecision(number_of_sig_figs) << number;
return std::stod(lStream.str());
})(sig_figs);
std::cout << "rounded number:" << number << std::endl;
Well there are good math libraries in math.h
Also storing your figures in floats, doubles or long doubles will allow for more precise operations.
Floats offer 7 significant digits while doubles offer 16 significant digits.
source
Also when printing out usually people use _snprintf or printf and you can format those doubles, floats to the precision you want like:
Float Precision
printf("Value %8.2f", floatVariable);
This says you require a total
field of 8 characters, within the 8
characters the last 2 will hold the
decimal part.
_snprintf(buffer, sizeof(buffer), "Value %.2f", floatVariable);
The example above
requests the minimum field width and
the last two characters are to hold
the decimal part.