问题
I was performing addition and subtraction on an input of decimals that are precise to the second decimal place. I tried to improve accuracy by converting them to integers through multiplying 100, but achieved opposite effects.
Consider the following code and output:
double d = 2.01;
int a = (int) (d * 100.0);
cout << a << endl;
The output is:
200
Once and for all, what are some of the best practices regarding floating-point arithmetics? Is it at all feasible to first convert the double to an int using some variant of the code above, and then casting it back?
回答1:
If you print out the result of d*100.0 to (say) 20 decimal places, the problem will quickly become apparent:
200.99999999999997
Since that's (ever so minutely) less than 201, it gets truncated to 200 when you cast to int.
The obvious cure is to force rounding. At least if your inputs are all positive that can be as simple as adding 0.5 to the result:
int a = (int)(d*100.0 + 0.5);
If you can count on your compiler supporting it, it's even easier to use the standard library's round:
long a = lround(d*100.0);
This works correctly for both positive and negative numbers.
回答2:
Use the standard math library's rounding functions. In C++ this means you will have to #include <cmath> and compile with -lm.
Then, for your example:
double d = 2.01;
long x = lround(d*100);
cout << x << endl; // prints 201, for sure.
This will be the same as the "add .5" trick, but it will work correctly for positive and negative numbers.
回答3:
Read this and reach enlightenment:
What Every Computer Scientist Should Know About Floating-Point Arithmetic
Floating-point arithmetic is considered an esoteric subject by many people. This is rather surprising because floating-point is ubiquitous in computer systems. Almost every language has a floating-point datatype; computers from PCs to supercomputers have floating-point accelerators; most compilers will be called upon to compile floating-point algorithms from time to time; and virtually every operating system must respond to floating-point exceptions such as overflow. This paper presents a tutorial on those aspects of floating-point that have a direct impact on designers of computer systems. It begins with background on floating-point representation and rounding error, continues with a discussion of the IEEE floating-point standard, and concludes with numerous examples of how computer builders can better support floating-point.
回答4:
In order to get well defined rouding, I would use floor() and ceil().
So, for the following code,
(int)floor( 2.01*100.)
I get:
200
But for:
(int)ceil(2.01*100.)
I get:
201
来源:https://stackoverflow.com/questions/24665459/best-practices-for-floating-point-arithmetics