C++ Rounding float-pointing value to number of fractional digits - c++

I have tried std::round but it doesn't give me result that I want exactly. So my question is I have program in C# and I am converting to C++ and I faced with this problem. C# Math.round and C++ round are different. So this causes wrong calculations.
C# code:
Console.WriteLine(Math.Round(0.850, 1));
Output:
0,8
C++ code:
std::cout << roundf(0.850f) << std::endl;
Output:
1
So like you see they are different. How can I solve this ?

The C# version is rounding a double to one decimal place, the C++ version is rounding a float to the nearest integer.
Rounding a binary floating point to a fixed number of decimal places doesn't really make much sense, as the rounded number will still most likely be an approximation. For example 0.8 cannot be represented exactly in binary floating point.
The C++ round function only rounds to the nearest integral value, which, given the above, is a sensible choice.
You can recover the C# behaviour (rounding to 1 decimal place) with std::round(0.850 * 10) / 10.
Note that I've dropped the f suffix to match the C# double type.

Related

Is a floating-point value of 0.0 represented differently from other floating-point values?

I've been going back through my C++ book, and I came across a statement that says zero can be represented exactly as a floating-point number. I was wondering how this is possible unless the value of 0.0 is stored as a type other than a floating point value. I wrote the following code to test this:
#include <iomanip>
#include <iostream>
int main()
{
float value1 {0.0};
float value2 {0.1};
std::cout << std::setprecision(10) << std::fixed;
std::cout << value1 << '\n'
<< value2 << std::endl;
}
Running this code gave the following output:
0.0000000000
0.1000000015
To 10 digits of precision, 0.0 is still 0, and 0.1 has some inaccuracies (which is to be expected). Is a value of 0.0 different from other floating point numbers in the way it is represented, and is this a feature of the compiler or the computer's architecture?
How can 2 be represented as an exact number? 4? 15? 0.5? The answer is just that some numbers can be represented exactly in the floating-point format (which is based on base-2/binary) and others can't.
This is no different from in decimal. You can't represent 1/3 exactly in decimal, but that doesn't mean you can't represent 0.
Zero is special in a way, because (like the other real numbers) it's more trivial to prove this property than for some arbitrary fractional number. But that's about it.
So:
what is it about these values (0, 1/16, 1/2048, ...) that allows them to be represented exactly.
Simple mathematics. In any given base, in the sort of representation we're talking about, some numbers can be written out with a fixed number of decimal places; others can't. That's it.
You can play online with H. Schmidt's IEEE-754 Floating Point Converter for different numbers to see a bunch of different representations, and what errors come about as a result of encoding into those representations. For starters, try 0.5, 0.2 and 0.1.
It was my (perhaps naive) understanding that all floating point values contained some instability.
No, absolutely not.
You want to treat every floating point value in your program as potentially having some small error on it, because you generally don't know what sequence of calculations led to it. You can't trust it, in general. I expect someone half-taught this to you in the past, and that's what led to your misunderstanding.
But, if you do know the error (or lack thereof) involved at each step in the creation of the value (e.g. "all I've done is initialised it to zero"), then that's fine! No need to worry about it then.
Here is one way to look at the situation: with 64 bits to store a number, there are 2^64 bit patterns. Some of these are "not-a-number" representations, but most of the 2^64 patterns represent numbers. The number that is represented is represented exactly, with no error. This might seem strange after learning about floating point math; a caveat lurks ahead.
However, as huge as 2^64 is, there are infinitely many more real numbers. When a calculation produces a non-integer result, the odds are pretty good that the answer will not be a number represented by one of the 2^64 patterns. There are exceptions. For example, 1/2 is represented by one of the patterns. If you store 0.5 in a floating point variable, it will actually store 0.5. Let's try that for other single-digit denominators. (Note: I am writing fractions for their expressive power; I do not intend integer arithmetic.)
1/1 – stored exactly
1/2 – stored exactly
1/3 – not stored exactly
1/4 – stored exactly
1/5 – not stored exactly
1/6 – not stored exactly
1/7 – not stored exactly
1/8 – stored exactly
1/9 – not stored exactly
So with these simple examples, over half are not stored exactly. When you get into more complicated calculations, any one piece of the calculation can throw you off the islands of exact representation. Do you see why the general rule of thumb is that floating point values are not exact? It is incredibly easy to fall into that realm. It is possible to avoid it, but don't count on it.
Some numbers can be represented exactly by a floating point value. Most cannot.

I'm trying to round a float to two decimal points but it's incorrect. How to fix this rounding error in C++?

I'm having trouble with rounding floats. I'm solving a task where you need to round your result to two decimal points. But I can't do it when the third decimal point is 5 because it's stored incorrectly.
For example: My result is equal to 1.005 and that should be rounded to 1.01. But C++ rounds it to 1.00 because the original float is stored as 1.0049999... and not 1.005.
I've already tried always adding a very small float to the result but there are some other test cases which are then rounded up but should be rounded down.
I know how floating-point works and that it is often not completely accurate. I'm just wondering whether anyone has found a way around this specific problem.
When you say "my result is equal to 1.005", you are assuming some count of true decimal digits. This can be 1.005 (three digits of fractional part), 1.0050 (four digits), 1.005000, and so on.
So, you should first round, using some usual rounding, to that count of digits. It is simpler to do this in integers: for example, with 6 fractional digits, it means some usual round(), rint(), etc. after multiplication by 1,000,000. With this step, you are getting exact decimal number. After this, you are able to make the required final rounding to what you need.
In your example, this will round 1,004,999.99... to 1,005,000. Then, divide by 10000 and round again.
(Notice that there are suggestions to make this rounding in yet specific way. The General Decimal Arithmetic specification and IBM arithmetic manuals suggest this rounding is done in the way that exact fractional part 0.5 shall be rounded away from zero unless least significant result bit becomes 0 or 5, in that case it is rounded toward zero. But, if you have no such rounding available, a general away-from-zero is also suitable.)
If you are implementing arithmetic for money accounting, it is reasonable to avoid floating point at all and use fixed-point arithmetic (emulated with integers, if needed). This is better because you the methods I've described for rounding are inevitably containing conversion to integers (and back), so, it's cheaper to use such integers directly. You will get inexact operation checking as well (by cost of explicit integer overflow).
If you can use a library like boost with its Multiprecision support.
Another option would be to use a long double, maybe that's precise enough for you.

How does computer convert floating point numbers to decimal string?

When I run the following code, the output is accurately the number 2500 in decimal.
(g++ 5.3.1 on ubuntu)
#include<iostream>
#include<cmath>
using namespace std;
int main(){
cout.precision(0);
cout << fixed << pow(2.0,500.0);
return 0;
}
I wonder how C++ converted this floating point number to its decimal string at such a high precision.
I know that 2500 can be accurately presented in IEEE 754 format. But I think mod 10 and divided by 10 can cause precision loss on floating point numbers. What algorithm is used when the conversion proceed?
Yes, there exists an exact double-precision floating-point representation for 2500. You should not assume that pow(2.0,500.0) produces this value, though. There is no guarantee of accuracy for the function pow, and you may find SO questions that arose from pow(10.0, 2.0) not producing 100.0, although the mathematical result was perfectly representable too.
But anyway, to answer your question, the conversion from the floating-point binary representation to decimal does not in general rely on floating-point operations, which indeed would be too inaccurate for the intended accuracy of the end result. In general, accurate conversion requires reliance on big integer arithmetics. In the case of 2500, for instance, the naïve algorithm would be to repeatedly divide the big integer written in binary 1000…<500 zeroes in total>… by ten.
There are some cases where floating-point arithmetic can be used, for instance taking advantage of the fact that powers of 10 up to 1023 are represented exactly in IEEE 754 double-precision. But correctly rounded conversion between binary floating-point and decimal floating-point always require big integer arithmetics in general, and this is particularly visible far away from 1.0.

Python 2.7 round 1 decimal not correct

Rounding on 1 decimal is not working correct:
See below:
round(11.35, 1)
11.3
round(1.35, 1)
1.4
How can this be solved in Python?
The solution of this problem is:
def round_decimal(value, rounding):
number = decimal.Decimal(str(value))
decimal_point = float("1e%d" % -rounding)
return float(number.quantize(decimal.Decimal(str(decimal_point))))
This is a problem with the representation of decimals in computers in general (so non-specific to Python).
The way I thought this is solved is by using the standard library module decimal. In your case it would look something like this:
num1 = decimal.Decimal("11.35")
print num1.quantize(decimal.Decimal("0.1")) # round to one decimal
# output: 11.4
num2 = decimal.Decimal("1.35")
print num2.quantize(decimal.Decimal("0.1"))
# output: 1.4
The reason for this is that 11.35 is held as a float which is stored using binary floating point representation. And 11.35 cannot be represented exactly as a binary floating point value.
Representable binary floating point values have the form s×2e where s and e are integers. Note that 11.35 cannot be written in this form. What happens in Python when you write 11.35 is that the system uses the closest representable value.
The closest double precision value to 11.35 is:
11.35 = + 11.34999 99999 99999 64472 86321 19949 90706 44378 66210 9375
This explains why round(11.35, 1) behaves as it does.
Interestingly, round(11.35, 1) isn't even exactly equal to 11.3 because 11.3 is not exactly representable using binary floating point. And so it goes on.
If you want to represent 11.35 exactly then you will need to store it in a decimal data type. The decimal standard library is the obvious way to do so in Python. This question covers that topic in some detail: How can I format a decimal to always show 2 decimal places?
In addition to the previous answers, I think it is helpful to know the rules of rounding. You assume that the value 11.35 should be rounded to 11.4, but in reality, rounding down is an option when you hit the mid-point value in rounding. See: http://en.wikipedia.org/wiki/Rounding
Using the decimal library is the best way to solve you issue in python for your case.

Subtracting double gives wrong result

I am trying to get the decimal part from the double and this is my code to get the decimal part
double decimalvalue = 23423.1234-23423.0;
0.12340000000040163
But after the subtraction I am expecting decimalvalue to be 0.1234 but I get 0.12340000000040163. Please help me to understand this behavior and if there is any workaround for it.
I suggest you have a look at
What Every Computer Scientist Should Know About Floating-Point Arithmetic
Wikipedia: IEEE 754
There are a finite number of values you can specify in a floating point number, but an infinite number of floating point numbers in the represented range.
Some floating point numbers therefore cannot be represented exactly in any floating/double style data type.
The typical way to handle your specific problem is to avoid a direct equality comparison, but rather do an epsilon test: See if the expected and computed values are within some small number (compared to the values being subtracted), called epsilon, of each other.
Indirectly related is the concept of Machine Epsilon, worth having a look at for a complete understanding
This is a rounding error. In base ten you cannot perfectly represent 1/3 in a given number of digits (say 15). In base 2 there are a lot more things you can not represent, 0.1234 happens to be one of them. The precision depends on the scale, but it's about 15 decimal digits for a double. I would suggest taking a look at http://en.wikipedia.org/wiki/IEEE_floating_point for more details on floating point numbers.
If you are trying to make a base 10 system (like a human used calculator for instance) and you need exact results you should use BCD.